Override privileged method of base class

前端 未结 2 914
没有蜡笔的小新
没有蜡笔的小新 2020-12-25 09:17

How can I go about making a child class override a privileged method of a base class?

If its not possible, is there another way to achieve what I am trying to accomp

相关标签:
2条回答
  • 2020-12-25 09:23

    IMO, you need to use a Javascript library like Ext Js to simplify this task. Anyway, the following example illustrates how you can write some helper methods. It's a part of an unreleased open source project that I'm working on.

    var JWObject = (function () {
    
        var jwobj = function (){};
    
        jwobj.prototype = { };
    
        return jwobj;
    
    })();
    
    var Prototype = (function () {
    
        var scopeQueue = [ window ];
    
        return {
    
            beginScope: function (namespace) {
                var parts = namespace.split('.');
                for (var i = 0; i < parts.length; i++) {
                    var name = parts[i],
                        parent = this.getScope(),
                        part = parent[name];
    
                    if (part && !part.__namespace) {
                        throw Error('/* ERROR MESSAGE */');
                    }
    
                    scopeQueue.push(parent[name] = (part || { __namespace: true }));
                }
            },
    
            endScope: function () {
                if (scopeQueue.length > 1) {
                    scopeQueue.pop();
                }
            },
    
            getScope: function () {
                return scopeQueue.pick();
            },
    
            define: function (name, members) {
    
                var scope = this.getScope();
    
                if (scope[name]) {
                    throw Error('The prototype already exist.');
                }
    
                this.extend(members, {
                    scope: scope,
                    extend: JWObject,
                    statics: {}
                });
    
                // Getting constructor
                var ctor = (members.constructor === Object) ? function() { } : members.constructor;
                delete members.constructor;
    
                if (typeof members.extend === 'string') {
                    members.extend = scope[members.extend];
                }
    
                if (!members.extend) {
                    throw Error('The base class is not specified.');
                }
    
                // Deriving from parent type
                ctor.prototype = new members.extend();
                members.super = members.extend.prototype;
                delete members.extend;
    
                members.statics.__class = true;
                this.extend(ctor, members.statics, true);
                delete members.statics;
    
                // Adding new members
                this.extend(ctor.prototype, members, true);
    
                // Adding and returning the created prototype
                return scope[name] = ctor;
    
            },
    
            extend: function (expando, members, override) {
                for (var m in members) {
                    if (override || !expando[m]) {
                        expando[m] = members[m];
                    }
                }
            }
    
        };
    
    })();
    
    Prototype.extend(Array.prototype, {
    
        pick: function() {
            return this[this.length - 1];
        }
    
    });
    

    Here is the result:

    Prototype.beginScope('Sample');
    
    /**
     * Prototype: Sample.Plugin
     */
    Prototype.define('Plugin', {
    
        init: function() {
            alert('init!');
        }
    
    });
    
    Prototype.beginScope('Extension');
    
    /**
     * Prototype: Sample.Extensions.Plugin
     * Extend   : Sample.Plugin
     */
    Prototype.define('Foo', {
        extend: Sample.Plugin,
    
        init: function() {
            this.super.init.call(this);
            alert('child: init!');
        },
    
        fun: function() {
            this.init();
        },
    
        statics: {
    
            create: function() {
                return new Sample.Extension.Foo();
            }
    
        }
    
    });
    
    Prototype.endScope();
    Prototype.endScope();
    

    As you can see in the preceding code, the Prototype object provides some functionality to defining a namespace (Prototype.beginScope, Prototype.endScope and Prototype.getScope) or defining a prototype (Prototype.define).

    You can inherit a prototype from another using extend like java.

    Prototype.define('Foo', {
        extend: Sample.Plugin,
    

    Or call the base class method as follows:

        init: function() {
            this.super.init.call(this);
    

    Also, every prototype you define with above code will be derived from JWObject by default.

    0 讨论(0)
  • 2020-12-25 09:26
    function BaseClass() {
        var map = {};
        this.parseXML = function(key, value) {
            alert("BaseClass::parseXML()");
            map[key] = value;
        }
    }
    
    function ChildClass() {
        BaseClass.call(this);
        var parseXML = this.parseXML;
        this.parseXML = function(key, value, otherData) {
            alert("ChildClass()::parseXML()");
            parseXML.call(this, key, value);
        }
    }
    
    ChildClass.prototype = new BaseClass;
    
    var a = new ChildClass();
    a.parseXML();
    

    Live Example

    Basically you cache the privileged method (which is only defined on the object) and then call it inside the new function you assign to the privileged method name.

    However a more elegant solution would be:

    function BaseClass() {
        this._map = {};
    };
    
    BaseClass.prototype.parseXML = function(key, value) {
        alert("BaseClass::parseXML()");
        this._map[key] = value;
    }
    
    function ChildClass() {
        BaseClass.call(this);
    }
    
    ChildClass.prototype = Object.create(BaseClass.prototype);
    ChildClass.prototype.parseXML = function(key, value, otherData) {
        alert("ChildClass()::parseXML()");
        BaseClass.prototype.parseXML.call(this, key, value);
    }
    
    var a = new ChildClass();
    a.parseXML();
    

    Live Example

    Also bonus implementation using pd

    0 讨论(0)
提交回复
热议问题