Reputation: 3936
I'm currently in the process of converting a quite large actionscript library to work in a nodejs project of mine. While doing so I stumbled upon something that could be an issue: Building classes from classes.
Is there a way to use an object as the base for another object(IE: inherits all members from the base object, then overwrites same name members from the extending object)?
Right now this is what I'm doing, though it's getting a bit difficult to manage now that there are 3+ classes built one on top of another:
// The base object which others may extend
function A() {
this.a = "pie";
}
A.prototype.yum = function() {
return this.a + " is AWESOME!";
}
// The "extends A" object.
// Instead of creating an instance of "B", I current just create an instance of "A",
// then adding the members from "B" to it at which point I return the "A" instance.
function B() {
var a = new A();
a.b = "pie";
// Notice how I have to declare the overwriting function here instead of being able
// to drop it into B's prototype. The reason this bothers me is instead of just
// having one copy of the function(s) stored, each time a "new B" is created the
// function is duplicated... for 100s of "B" objects created, that seems like poor
// memory management
a.yum = function () {
return "I like " + this.a + " and " + this.b;
};
return a;
}
console.log((B()).yum());
Is it possible to do something along the following?
I know this isn't valid, but it gives the idea.
function A(){
this.a = "pie"
}
A.prototype.yum = function () {
return this.a + " is AWESOME!";
}
function B(){
// Throws an "illegal left hand assignment" Exception due to overwriting `this`;
this = new A();
this.b = "cake"
}
B.prototype.yum = function () {
return "I like "+this.a+" and "+this.b;
}
console.log((new B()).yum());
Notes:
1: I know javascript doesn't have classes; it uses objects and prototypes. Otherwise I wouldn't be asking.
2: This isn't the actual code im (trying) to convert; it's a generalized example
3: Please do not suggest a library. I know at times they are valuable, but I'd rather not have to maintain, depend on and include an entire library for the project.
ANSWER: I know it's bad form to alter native member prototypes, but I think this merits it, due to the lack of possible functionality, and the size of it.
Object.prototype.extendsUpon = function (p) {
var h = Object.prototype.hasOwnProperty;
for(var k in p)if(h.call(p,k))this[k]=p[k];
function c(c){this.constructor=c;}
c.prototype = p.prototype;
this.prototype = new c(this);
this.__base__ = p.prototype;
}
function object_Constructor_built_ontop_of_another_constructor() {
this.extendsUpon(base_Object_to_built_atop_off);
this.__base__.constructor.apply(this, arguments);
// From here proceed as usual
/* To access members from the base object that have been over written,
* use "this.__base__.MEMBER.apply(this, arguments)" */
}
Upvotes: 0
Views: 56
Reputation: 1692
Very much possible. You can do it in multiple ways, the more complete is used in coffeescript:
var ClassBase, ClassTop,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
ClassBase = (function() {
function ClassBase() {}
return ClassBase;
})();
ClassTop = (function(_super) {
__extends(ClassTop, _super);
function ClassTop() {
return ClassTop.__super__.constructor.apply(this, arguments);
}
return ClassTop;
})(ClassBase);
There is going to be some boilerplate code. ClassTop
is inheriting everything from ClassBase
. The classes don't have much inside them other then an __extend
, a (function(_super...
and some constructor boilerplate but it's fairly simple.
The inheritance is mostly managed by the __extends
boilerplate that does some magic. The full __extends
method is beautified here:
__extends = function (child, parent) {
for (var key in parent) {
if (__hasProp.call(parent, key)) child[key] = parent[key];
}
function ctor() {
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
return child;
};
Again, much less scary then before. You're basically checking properties that the parent has and applying them to the child. More information can be found here: http://www.jimmycuadra.com/posts/coffeescript-classes-under-the-hood
Upvotes: 1