Skip to content

Instantly share code, notes, and snippets.

@jakevdp
Last active August 29, 2015 13:57
Show Gist options
  • Save jakevdp/9613560 to your computer and use it in GitHub Desktop.
Save jakevdp/9613560 to your computer and use it in GitHub Desktop.
A simple Javascript inheritance pattern
/**********************************************************************
I've been working with javascript for a bit, and I miss my
Python-style namespaces and class inheritance. Here's a little
pattern I came up with that allows me to do things (kind of)
the way I wish I could within javascript. I'd be curious if any
experienced JS users have comments or critiques. Thanks!
Edit - also see the second version (which I think is more clean)
below.
**********************************************************************/
/* this is an anonymous function which defines the namespace myModule */
!(function(){
var myModule = {};
/* subClass function implements simple inheritance */
function subClass(base, derived){
derived = (typeof derived === "function") ? derived : function(){};
derived.prototype = new base();
derived.prototype.constructor = derived;
derived.subClass = function(child){return subClass(derived, child);};
return derived;
}
/* Create a Base class */
myModule.Base = subClass(Object, Base);
function Base(){}
Base.prototype.foo = function(){
console.log("call Base.foo()");
};
Base.prototype.bar = function(){
console.log("call Base.bar()");
};
/* Create a Derived class with specialized bar() method */
myModule.Derived = Base.subClass(Derived);
function Derived(x){
console.log("initializing Derived(x = " + x + ")");
}
Derived.prototype.bar = function(){
console.log("call Derived.bar()");
};
/* put myModule in the global namespace */
this.myModule = myModule;
})();
/*--------------------------------------------------------------------------*/
/* Everything below is depends on the module definition above. */
/* We'll create an object and call both base and derived methods */
var obj = new myModule.Derived(10); //--> "initializing Derived(x = 10)"
console.log(obj); //--> "Derived {...}"
obj.foo(); //--> "call Base.foo()"
obj.bar(); //--> "call Derived.bar()"
/**********************************************************************
Here's another version, which sets up a ``$sub`` method for a base
class named ``Class``. I think I like this pattern better...
**********************************************************************/
// anonymous function to define ``Class``
// we pass undefined explicitly in case it has been globally modified.
!function(undefined){
var _noInit, Class = $sub(Object);
function $sub(Base, methods){
function SubClass(){
if(!_noInit && this.__init__)
return this.__init__.apply(this, arguments);
}
_noInit = true; SubClass.prototype = new Base; _noInit = false;
SubClass.prototype.constructor = SubClass;
for(m in methods){ SubClass.prototype[m] = methods[m]; }
SubClass.$sub = $sub.bind(this, SubClass);
return SubClass;
}
this.Class = Class;
}();
var Base = Class.$sub({
__init__: function(){console.log("constructing Base");},
foo: function(){console.log("Base.foo");},
bar: function(){console.log("Base.bar(" + this.x + ")");},
x: 0,
});
var Derived = Base.$sub({
__init__: function(x){this.x = x;},
foo: function(){console.log("Derived.foo(" + this.x + ")");},
});
obj = new Base(); // "constructing Base"
obj.foo(); // "Base.foo"
obj.bar(); // "Base.bar(0)"
obj = new Derived(4);
obj.foo(); // "Derived.foo(4)"
obj.bar(); // "Base.bar(4)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment