Search code examples
javascriptinheritancesmalltalksuper

Javascript inheritance with access to *all* methods in 'superclass'?


Trying to understand how inheritance can be done in Javascript, I stumbled across many differerent implementations, including Crockfords, Resigs, Prototype, klass, and others.

What I missed (I brace myself for the uproar) was the Smalltalkish self/super pair: self playing a similar role than this, namely representing the current "object", and super referring to a superclass-only version of this.

[Skip to "]" if you know what super does in Smalltalk: Assuming Subclass has overriden method1 defined in Superclass, I can still access the superclass implementation using super.method1() in Subclass.method2(). This will not execute the Subclass.method1() code.

function Superclass () {
}
Superclass.prototype.method1 = function () {
  return "super";
}

function Subclass () {
}
Subclass.prototype.method1 = function () {
  return "sub";
}
Subclass.prototype.method2 = function () {
  alert (super.method1 ());
}

var o = new Subclass;
o.method2 (); // prints "super"

]

Is there any "Javatalk" package out there? So far, I have seen only OO emulations in Javascript which give access to the superclass implementation of the currently defined method (method2), not any other (such as method1).

Thanks, nobi


Solution

  • There are so many ways to implement a super feature in JavaScript. For instance:

    function SuperClass(someValue) {
        this.someValue = someValue;
    }
    
    SuperClass.prototype.method1 = function () {
        return this.someValue;
    };
    
    function SubClass(someValue) {
        //call the SuperClass constructor
        this.super.constructor.call(this, someValue);
    }
    
    //inherit from SuperClass
    SubClass.prototype = Object.create(SuperClass.prototype);
    
    //create the super member that points to the SuperClass prototype
    SubClass.prototype.super = SuperClass.prototype;
    
    SubClass.prototype.method2 = function () {
        alert(this.super.method1.call(this));
    };
    
    var sub = new SubClass('some value');
    
    sub.method2();
    

    EDIT:

    Here's an example of an extremely generic super method that relies on non-standard features. I really do not recommend this and it's just there as learning purposes.

    Object.prototype.super = function () {
        var superProto = Object.getPrototypeOf(Object.getPrototypeOf(this)),
            fnName = arguments.callee.caller.name,
            constructorName = this.constructor.name;
    
        if (superProto == null) throw constructorName + " doesn't have a superclass";
        if (typeof superProto[fnName] !== 'function') {
            throw constructorName + "'s superclass (" 
                + superProto.constructor.name + ") doesn't have a " + fnName + ' function';
        }
    
        return superProto[arguments.callee.caller.name].apply(
            this, 
            [].slice.call(arguments, 1)
        );
    };   
    
    
    function A() {
    }
    
    A.prototype.toString = function toString() {
        //call super method Object.prototype.toString
        return this.super();
    };
    
    var a = new A();
    
    console.log(a.toString());