开发者

Is there a good pattern for JavaScript calling overridden functions in a parent without knowing the specific parent?

Basically I want inheritable functions as in

Base = function() { };

Base.prototype.foo = function() {
  console.log("base foo");
};

Derived = function() { };

somelib.inherit(Derived, Base);

Derived.prototype.foo = function() {
  console.log("derived foo");
}

d = new Derived():
d.foo();

And I want it to print

derived foo
base foo

Yes I know I can explicitly call Base.prototype.foo.call(this); I'm just wondering if there is a pattern for calling overridden super class functions automatically. The problem I'm trying to solve is 2 fold.

  1. derived classe开发者_Python百科s should NOT have to remember to call their parent's method, it just happens automatically.
  2. if 1. can't happen then at least I'd like Derived not to call Base by name since that's brittle. Rather I'd like it call parentclass or something so you don't have to know the base. That way if you change the name of the base you don't have to go fixing every derived class.


You can implement such functionality by using a structure like:

function Base(){}
Base.prototype.destroy = function(){console.log('Base destroy');};

function Derived(){}
Derived.prototype = new Base; // Let Derived inherit from Base

// Override the `destroy` method
Derived.prototype.destroy = function() {
    console.log('Derived destroy');

    // Call parent class method
    this.constructor.prototype.destroy();
    // If the context of the method is important, you can use Function.call:
  //this.constructor.prototype.destroy.call(this);
};


// Create an instance of Derived, and call the destroy method:
(new Derived).destroy();


I would suggest thinking about exactly why you are doing this, at least in terms of requirement #1. Keep in mind that your desired pattern would take away a great deal of flexibility. For instance, if you have a situation where you want to print the statements in the opposite order:

    base foo
    derived foo

You would either have to abandon your pattern or create a function foo2() in the derived class which then calls foo() in the base class. Neither is very pretty.

Same goes if you even want to do something as simple as:

    derived foo
    base foo
    one more thing in the derived function

I would contend that using this pattern may work for the exact thing you want to do right now, but may give you fits when you want to make a seemingly trivial change down the road. All to save one line of code!


As far as I know there is no language integrated destructor functionality in JavaScript. It is all about frameworks. If you are using ASP.NET Ajax, for example, the framework would expect that your objects would have a dispose method, responsible for freeing up resources (event handlers). So, it is up to you.


Ok, this isn't quite what you are looking for, in that it's not a "pattern", but it is a potential implementation path you could follow:

Take a look @ the MooTools Class.Extras package (for lack of a better word). Using the Chain Class, you could probably get the desired functionality.


var parent = (function () {
    var construct = function () {
    };

    construct.prototype = {
        constructor: construct,
        destroy: function () {
            console.log('parent destruction');
        }
    }

    return construct;
})();

var child = (function (parent) {
    var construct = function () {
    };

    construct.prototype = Object.create(parent.prototype);

    construct.prototype.constructor = construct;
    construct.prototype.destroy = function () {
       parent.prototype.destroy.call(this); // calling parent, too
       console.log('child destruction');
    };

    return construct;
})(parent);

child_instance = new child();
child_instance.destroy();


I would prefer a way where I don't assign Derived = chainify() so that the api would be the same as you had in your question but as of right now this is the best way I can get it to work. It works by replacing each method of the object with a method that calls the replaced method and travels up the parent chain calling their methods along the way.

function chainify() {
    return function () {
        var property;
        for (property in this) {
            if (typeof this[property] === "function") {
                this[property] = chain(this[property], property);
            }
        }
        function chain(method, method_name) {
            return function() {
                method();
                var current = this;
                while (current = current.parent) {
                    if (current.hasOwnProperty(method_name)) {
                        current[method_name].apply(this, arguments);
                    }
                }
            };
        }
    }
}
var somelib = function() { };

somelib.inherit = function (derive, base) {
    derive.prototype = new base;
    derive.prototype.parent = base.prototype;
};

var Base = function() { };

Base.prototype.foo = function() {
  console.log("base foo");
};

var Derived = chainify();

somelib.inherit(Derived, Base);

Derived.prototype.foo = function() {
  console.log("derived foo");
};

d = new Derived();
d.foo();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜