Javascript 覆盖基类的特权方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8031467/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 04:27:18  来源:igfitidea点击:

Override privileged method of base class

javascriptinheritanceoverriding

提问by sazr

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 accomplish in the simple code example below?

如果不可能,是否有另一种方法可以实现我在下面的简单代码示例中想要完成的任务?

I cannot convert the baseclass function parseXML() to public because it requires access to private variables

我无法将基类函数 parseXML() 转换为 public,因为它需要访问私有变量

    function BaseClass()
    {
        var map = {};

        // I cannot make this function public BECAUSE it accesses & changes private variables
        this.parseXML = function( key, value )
        {
            alert("BaseClass::parseXML()");
            map[key] = value;
        }
    }

    function ChildClass()
    {
        BaseClass.call(this);
        this.parseXML = function( key, value, otherData )
        {
            alert("ChildClass()::parseXML()");

            // How can I call the base class function parseXML()?
            //this.parseXML();  // calls this function not the parent function
            //MyClass.prototype.doStuff.call
            BaseClass.prototype.parseXML.call(this, key, value);  // fails
            //BaseClass.prototype.parseXML(); // fails

            // perform specialised actions here with otherData
        }
    }

    ChildClass.prototype = new BaseClass;

    var a = new ChildClass();
    a.parseXML();

回答by Raynos

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

奖金实施使用pd

回答by Mehdi Golchin

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.

IMO,您需要使用像 Ext Js 这样的 Javascript 库来简化此任务。无论如何,以下示例说明了如何编写一些辅助方法。它是我正在从事的一个未发布的开源项目的一部分。

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.endScopeand Prototype.getScope) or defining a prototype (Prototype.define).

正如您在前面的代码中看到的,Prototype 对象提供了一些功能来定义命名空间(Prototype.beginScope,Prototype.endScopePrototype.getScope)或定义原型(Prototype.define)。

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

您可以使用像 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.

此外,默认情况下,您使用上述代码定义的每个原型都将从 JWObject 派生。