class sugar: static inheritance

Bob Nystrom rnystrom at google.com
Wed Jun 8 12:57:47 PDT 2011


On Wed, Jun 8, 2011 at 11:50 AM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:

> One of their main points is that the extensibility interface that a class
> exposes to subclasses should be treated as a distinct interface from the
> interface that the classes exposes to external clients.
>

This is an excellent insight. When I'm in a static language, I definitely
like making these two explicitly different. (I tend to go farther and make a
distinction between the interface a class exposes to its subclass and the
interface it uses for its own methods, which leads to me making most
protected methods abstract or with empty bodies.)

In Javascript, I typically make the distinction through documentation or
naming convention. A simple // protected goes a long way if you trust your
coworkers. If you want to make it a little more explicit, JS gives us enough
fun toys to do that. Where in Java I'd do:

class FacePainter {
  // Interface to outside world:
  public void paint(int x, int y) {
    drawCircle(x, y, 40); // face
    drawCircle(x + 10, y + 10, 10, 10); // eye
    drawCircle(x + 30, y + 10, 10, 10); // eye
    drawArc(x + 10, y + 10, 20); // mouth
  }

  // Interface to subclass:
  protected abstract void drawCircle(int x, int y, int radius);
  protected abstract void drawArc(int x, int y, int radius);
}

class CanvasFacePainter extends FacePainter {
  protected void drawCircle(int x, int y, int radius) {
    // draw on canvas...
  }

  protected abstract void drawArc(int x, int y, int radius) {
    // draw on canvas...
  }
}


In Javascript, I can do:

class FacePainter {
  // Interface to outside world:
  paint(x, y) {
    this.painter_.drawCircle(x, y, 40); // face
    this.painter_.drawCircle(x + 10, y + 10, 10, 10); // eye
    this.painter_.drawCircle(x + 30, y + 10, 10, 10); // eye
    this.painter_.drawArc(x + 10, y + 10, 20); // mouth
  }

  // Interface to subclass:
  constructor(painter) {
    this.painter_ = painter;
  }
}

class CanvasFacePainter extends FacePainter {
  constructor({
    drawCircle: function(x, y, radius) {
      // draw on canvas...
    },
    drawArc: function(x, y, radius)
      // draw on canvas...
    }
  }) {}
}


By stuffing all of the "protected" methods into a single field that the
instance stores, they aren't a visible part of FacePainter's interface
unless you go out of your way to get them through painter_. That should be
enough of a velvet rope to make it clear you're wandering somewhere you're
not supposed to go.

Patterns like this have the advantage of supporting more than two
interfaces. Where public/protected lets you define two windows, "to
everyone" and "to my subclass", using composition to form those interfaces
lets you define more fine-grained ones like "to the rendering system" or "to
the UI layer".

- bob


> A concrete technique for this is the use of the template method pattern
> (for example, http://www.oodesign.com/template-method-pattern.html ) which
> is one of the GOOF patterns.  In this pattern, an abstract algorithm is
> represented as template method with explicit this method calls at each
> extension point.  Subclasses are expected to over-ride does methods as a
> means of configuring the abstract algorithm.
>
> protected if implemented with a reasonable semantics is a way to support
> such reuse patterns.  For example, protected provides a way to formalize the
> subclass extensibility contract.  It is the protected methods that define
> that contract.  Similarly, the this call-backs in a template method really
> define such a reusability contract and should be specified in terms of
> protected methods.
>
> We are on a well trod path here. protected is an important paving stone.
>
> Allen
>
>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110608/c86eadd2/attachment.html>


More information about the es-discuss mailing list