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
Override privileged method of base class
提问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();
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();
回答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.endScope
and Prototype.getScope
) or defining a prototype (Prototype.define
).
正如您在前面的代码中看到的,Prototype 对象提供了一些功能来定义命名空间(Prototype.beginScope
,Prototype.endScope
和Prototype.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 派生。