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