Michael Schuerig
2005-Sep-25 11:05 UTC
[Rails-spinoffs] Prototype "classes" and inheritance
JavaScript doesn''t (yet) have a notion of classes. Prototype.js just
adds a suitable convention for implementing them. It provides a way to
create a new class by extending a base class using Object.extend, but
it doesn''t handle method inheritance. There are ways of doing
implementing this through traversing the chain of prototypes, but I''m
not sure they are compatible with the way prototype.js handles classes.
Below is my simplistic implementation for single-level inheritance. See
the unit tests for how it works. I appreciate suggestions for
improvement.
Michael
Object.inherit = function(destination, source, ctorStyle) {
for (property in source) {
var superMethod = destination[property];
if (superMethod && typeof superMethod ==
''function'') {
destination[''_super_'' + property] = superMethod;
}
destination[property] = source[property];
}
if (ctorStyle && ctorStyle != ''explicitSuperCtor'') {
var _derived_initialize = destination.initialize;
var _super_initialize = destination._super_initialize;
destination[''initialize''] = function() {
_super_initialize.apply(this, arguments);
_derived_initialize.apply(this, arguments);
}
delete destination._super_initialize;
}
return destination;
}
testObject_extend_with_super: function() { with(this) {
var superInitArgs, method1Args, method2Args;
var Super = Class.create();
Super.prototype = {
initialize: function() {
superInitArgs = arguments;
},
method1: function() {
method1Args = arguments;
},
method2: function() {
method2Args = arguments;
}
};
var Derived = Class.create();
Derived.prototype = Object.inherit(Super.prototype, {
initialize: function() {
},
method1: function() {
this._super_method1.apply(this, arguments);
},
method2: function() {
this._super_method2(''changed arg'');
}
}, true);
var derived = new Derived(''ctor arg'');
assertEqual(''ctor arg'', superInitArgs[0]);
derived.method1(''method arg'')
assertEqual(''method arg'', method1Args[0]);
derived.method2(''method arg'')
assertEqual(''changed arg'', method2Args[0]);
}},
testObject_extend_with_super_ctor_explicit: function() { with(this) {
var superInitArgs;
var Super = Class.create();
Super.prototype = {
initialize: function() {
superInitArgs = arguments;
}
};
var Derived = Class.create();
Derived.prototype = Object.inherit(Super.prototype, {
initialize: function() {
this._super_initialize(''explicit ctor arg'');
}
}, ''explicitSuperCtor'');
var derived = new Derived(''ctor arg'');
assertEqual(''explicit ctor arg'', superInitArgs[0]);
}},
--
Michael Schuerig I am the sum total of the parts
mailto:michael@schuerig.de I control directly.
http://www.schuerig.de/michael/ --Daniel C. Dennett, Elbow Room
Michael Schuerig
2005-Sep-25 11:50 UTC
[Rails-spinoffs] Re: Prototype "classes" and inheritance
On Sunday 25 September 2005 16:40, Michael Schuerig wrote:
[snip]
Scratch the earlier version. This one''s better.
Note to self: Unit testing only helps when testing the right things.
Michael
Object.inherit = function(superClass, derivedClass, ctorStyle) {
var _super_initialize = superClass.initialize;
var _derived_initialize = derivedClass.initialize;
for (property in superClass) {
var superMethod = superClass[property];
if (superMethod && typeof superMethod ==
''function'') {
derivedClass[''_super_'' + property] = superMethod;
}
if (!derivedClass.hasOwnProperty(property)) {
derivedClass[property] = superClass[property];
}
}
if (!ctorStyle || ctorStyle != ''explicitSuperCtor'') {
derivedClass[''initialize''] = function() {
_super_initialize.apply(this, arguments);
_derived_initialize.apply(this, arguments);
}
delete derivedClass._super_initialize;
}
return derivedClass;
}
testObject_inherit: function() { with(this) {
var superInitArgs, method1Args, method2Args;
var Super = Class.create();
Super.prototype = {
initialize: function() {
superInitArgs = arguments;
},
method1: function() {
method1Args = arguments;
},
method2: function() {
method2Args = arguments;
}
};
var Derived = Class.create();
Derived.prototype = Object.inherit(Super.prototype, {
initialize: function() {
},
method1: function() {
this._super_method1.apply(this, arguments);
},
method2: function() {
this._super_method2(''changed arg'');
}
});
var derived = new Derived(''ctor arg'');
assertEqual(''ctor arg'', superInitArgs[0]);
derived.method1(''method arg'')
assertEqual(''method arg'', method1Args[0]);
derived.method2(''method arg'')
assertEqual(''changed arg'', method2Args[0]);
}},
testObject_inherit_with_explicit_super_ctor_call: function()
{ with(this) {
var superInitArgs;
var Super = Class.create();
Super.prototype = {
initialize: function() {
superInitArgs = arguments;
}
};
var Derived = Class.create();
Derived.prototype = Object.inherit(Super.prototype, {
initialize: function() {
this._super_initialize(''explicit ctor arg'');
}
}, ''explicitSuperCtor'');
var derived = new Derived(''ctor arg'');
assertEqual(''explicit ctor arg'', superInitArgs[0]);
}},
--
Michael Schuerig They tell you that the darkness
mailto:michael@schuerig.de Is a blessing in disguise
http://www.schuerig.de/michael/ --Janis Ian, From Me To You