Inheritance (again)

13 views
Skip to first unread message

Michael

unread,
Nov 5, 2010, 8:47:51 PM11/5/10
to base2-js
I'm back to (my annual) looking at the base class in an effort to
actually understand how it all works rather than just being content to
use it and stumbled upon something that is confusing me a bit. Taking
an example of Deans from http://dean.edwards.name/weblog/2006/03/base/

var Circle = Shape.extend({ // instance interface
constructor: function(x, y, radius) {
this.base(x, y);
this.radius = radius;
},

radius: 0,

getCircumference: function() {
return 2 * Circle.PI * this.radius;
}
}, { // class interface
PI: 3.14
});

radius is defined in two places here (is it?). The radius property in
the instance interface adds a radius property to Circle.prototype
while the this.radius in the constructor adds a property radius to the
current instance of Circle. Am I right in thinking the two are not
really the same thing, or does the this.radius in the constructor
refer to the same thing as it exists at this point?

Take the case of Circle looking like this:

var Circle = Shape.extend({ // instance interface
constructor: function (x, y, radius) {
this.base(x, y);
this.coords.push([x,y]);
this.radius = radius;
},

radius: 0,
coords: [],

getCircumference: function () {
return 2 * Circle.PI * this.radius;
}
}, { // class interface
PI: 3.14
});

coords here is shared between all instances of Circles, and so the
second circle created has two points in it's coords, the third three
etc. I think perhaps the 'instance interface' should not define
properties of the instance, but that these should always be defined
with the syntax this.propname = value in the constructor function???
I think the examples on the page mentioned above only work because the
properties use immutable types (strings and numbers)?

Seeking clarification really - I'm so close to understanding this time

Dean Edwards

unread,
Nov 17, 2010, 3:14:45 PM11/17/10
to base...@googlegroups.com, Michael
On 06/11/2010 00:47, Michael wrote:
> I'm back to (my annual) looking at the base class in an effort to
> actually understand how it all works rather than just being content to
> use it and stumbled upon something that is confusing me a bit. Taking
> an example of Deans from http://dean.edwards.name/weblog/2006/03/base/
>
> var Circle = Shape.extend({ // instance interface
> constructor: function(x, y, radius) {
> this.base(x, y);
> this.radius = radius;
> },
>
> radius: 0,
>
> getCircumference: function() {
> return 2 * Circle.PI * this.radius;
> }
> }, { // class interface
> PI: 3.14
> });
>
> radius is defined in two places here (is it?). The radius property in
> the instance interface adds a radius property to Circle.prototype
> while the this.radius in the constructor adds a property radius to the
> current instance of Circle. Am I right in thinking the two are not
> really the same thing, or does the this.radius in the constructor
> refer to the same thing as it exists at this point?

radius is a property of each Circle object. It is initialised by the
radius parameter passed to the constructor function.

> Take the case of Circle looking like this:
>
> var Circle = Shape.extend({ // instance interface
> constructor: function (x, y, radius) {
> this.base(x, y);
> this.coords.push([x,y]);
> this.radius = radius;
> },
>
> radius: 0,
> coords: [],
>
> getCircumference: function () {
> return 2 * Circle.PI * this.radius;
> }
> }, { // class interface
> PI: 3.14
> });
>
> coords here is shared between all instances of Circles, and so the
> second circle created has two points in it's coords, the third three
> etc.

You can't define a coords object in the class definition. The coords
array would be shared by all instances. Instead, you should create a new
array in the constructor function:

var Circle = Shape.extend({ // instance interface
constructor: function (x, y, radius) {

this.coords = [x, y];
this.radius = radius;
},

radius: 0,
coords: null, // created in the constructor function

getCircumference: function () {
return 2 * Circle.PI * this.radius;
}
}, { // class interface
PI: 3.14
});

Is that a bit clearer?

If you want something simpler to study then you can look at John Resig's
Simple Inheritance:

http://ejohn.org/blog/simple-javascript-inheritance/

It is essentially a rewrite of Base but it is a bit easier to understand.

-dean

doekman

unread,
Nov 18, 2010, 3:37:57 AM11/18/10
to base2-js
Maybe Michael is put on the wrong track, because coords and radius are
used in two places, namely in the constructor (this.coords = [x,y];
this.radius = radius), and as property (radius: 0, coords: null).

For as far as I can see it are the properties not really necessary to
get it working.
So the following should work as well (correct me if I'm wrong):

var Circle = Shape.extend({ // instance interface
constructor: function (x, y, radius) {
this.coords = [x, y];
this.radius = radius;
},

getCircumference: function () {
return 2 * Circle.PI * this.radius;
}
}, { // class interface
PI: 3.14
});

Doeke




On Nov 17, 10:14 pm, Dean Edwards <dean.edwa...@gmail.com> wrote:
> On 06/11/2010 00:47, Michael wrote:
>
>
>
>
>
>
>
>
>
> > I'm back to (my annual) looking at the base class in an effort to
> > actually understand how it all works rather than just being content to
> > use it and stumbled upon something that is confusing me a bit.  Taking
> > an example of Deans fromhttp://dean.edwards.name/weblog/2006/03/base/

Michael Hodgson

unread,
Nov 18, 2010, 4:38:58 AM11/18/10
to base...@googlegroups.com
Doeke,

  thanks for this,  and apologies to dean for the repeat post (forgot to reply to the list).  You've hit the nail on the head really. 

  I had seen John's example and it was in fact that article that prompted me to look again at base2 (John also mentions the base2 inheritance model in his book).  I think I understand what's going on now.

  I understand that I have to initialize properties in the constructor....  I suppose the question was what does it add to define them in the object literal that is passed to extend (as the _instance parameter).  If they are not passed as part of the _instance argument then they don't become part of the prototype, but are still properties of every instance when created in the constructor.  As any properties initialized in the constructor will effectively hide the prototype property, the prototype property is redundant?  I had thought this wasteful, but I guess it's insignificant given the small number of classes/constructor functions compared to instances.

  Basically why is

var Circle = Shape.extend({ // instance interface
  constructor: function(x, y, radius) {
    this.base(x, y);
    this.radius = radius;
  },
  radius: 0
});

any better than

var Circle = Shape.extend({ // instance interface
  constructor: function(x, y, radius) {
    this.base(x, y);
    this.radius = radius;
  }
});

In usage they surely do the same thing, just slightly (insignificantly) shorter code, and a few less prototype properties.  I don't think it matters, I was just a bit worried when I first worked out what was going on.  Since then of course I realise that you encounter a similar situation whenever you do:

var MyClass = function(){}
MyClass.prototype = new Circle();

Of course MyClass prototype has a radius property too, but nobody seems to worry :)  This is not a feature just of base2 but the whole approach of inheritance in JavaScript.  I guess all I am worried about is that I forget to initialize a property in the constructor, especially if dealing with an inherited class.  It's not hard to imagine forgetting to initialize something, or forgetting to call a base constructor that is responsible for initialising some property, and having code that misbehaves in an unpredictable fashion. You simplify it to debug (down to a single instance) and it works...  I can feel my brain hurting already.  


Michael 

doekman

unread,
Nov 18, 2010, 5:57:17 AM11/18/10
to base2-js
Micheal,

glad I could help.

And yes, I see the properties (radius: 0) mostly as documentation, but
also to initialize them with (sensible) default values. And those
default values are also documenting ;-)

Doeke



On Nov 18, 10:38 am, Michael Hodgson <michael.hodg...@gmail.com>
wrote:
Reply all
Reply to author
Forward
0 new messages