Hey there,
> Square.prototype = Object.extend(new Shape(), {
OK, this is trouble in our case. Justin told so in his article already.
Doing this, basically, has problems. This is because code executed by
the constructor (including code in initialize, if your constructor is
provided by Class.create) will happen right there and then, in your new
Shape. The dependency scheme here goes:
o = new Shape() => { options: 'parent', array: ['hj', 'jenny'] }
|
refs copied to (that's what Object.extend *does*...)
|
+-- Square.prototype => { options: o.option, array: o.array }
|
+-- sq1 => { options: o.option, array: o.array, foo: 'I am foo' }
|
+-- sq2 => { options: o.option, array: o.array, foo: 'I am foo' }
The array is created once, by new Shape(), and the reference is copied
over to Square.prototype. The properties are then copied over (as refs,
as always...) to the instances sq1 and sq2.
Nominal behavior, although undesirable.
Not to mention you create a Shape from the start.
You *will* find Object.extend(new X, {...}) in Prototype (for
Insertions, Event- and TimedObservers, and Ajax requesters), but if you
look carefully, the constructor functions for the base objects do not
call initialize, nor do they initialize any container field where
ref-copy would be a problem:
- they're either empty (Ajax.Base, Abstract.TimedObserver,
Abstract.EventObserver)
- or innocuous (Abstract.Insertion, which just defines adjacency, then
used by the child objects' initialize function).
Indeed, this scheme is the main problem in Prototype's current
inheritance system. Core is keeping an eye on Dean Edwards' Base
paradigm and may decide to move Prototype's system to it for 2.0, but
that's a long time from now (at the very, very least by late 2007).
In the meantime, here's a suggested fix. WARNING: this certainly works,
but I haven't tested AT ALL whether this breaks anything in Prototype
(which it may well do, although I kinda intuit it doesn't). It relies on:
1) redefining Class.create to accept a "parent" class argument
2) not using Object.extend anymore: just define your child class
prototypes like you would the parent class.
Check this out:
Class.create = function(base) {
return function() {
if ((base) && base.prototype.initialize)
base.prototype.initialize.apply(this, arguments);
this.initialize.apply(this, arguments);
}
};
var Parent = Class.create();
Parent.prototype = {
initialize: function() {
this.arr = ['hj', 'jenny'];
}
};
var Child = Class.create(Parent);
Child.prototype = {
initialize: function(name) {
this.name = name;
}
};
var c1 = new Child('john');
var c2 = new Child('mary');
c1.name // => 'john'
c2.name // => 'mary'
c1.arr.push('hey!');
c1.arr // => ['hj', 'jenny', 'hey!']
c2.arr // => ['hj', 'jenny', 'hey!']
--
Christophe Porteneuve a.k.a. TDD
"[They] did not know it was impossible, so they did it." --Mark Twain
Email: [EMAIL PROTECTED]
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby
on Rails: Spinoffs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/rubyonrails-spinoffs?hl=en
-~----------~----~----~----~------~----~------~--~---