[英]JavaScript: 'this' in superclass refers to subclass
我正在从子类调用超类方法。 当从子类调用时,超类方法中的“this”不再指代超类,而是指调用它的子类。 这会导致 inheritance 出现问题。
详情如下:
在我的项目中,我使用 class 从注册类型构造对象。 这些类型是从属性中注册的,或者是从基于已定义类型的模板中注册的:
class A{
createObject(type) {
let object = null;
for (let i in this.objecttypes) {
if (this.objecttypes[i].type == type) {
if (this.objecttypes[i].template) {
object = this.createObject(this.objecttypes[i].template);
object.type = type;
}
else
object = new TestObject(type);
for (const aname in this.objecttypes[i].attributes)
object.set(aname, this.objecttypes[i].attributes[aname]);
//console.log("Object: "+JSON.stringify(object));
}
}
return object;
}
}
这在超类中运行良好。 但是,我还构建了一个具有更用户友好方法的子类。 在子类中,名为“createObject”的方法不返回创建的 object。 它存储它并返回 object id:
class B extends A{
createObject(type,otherargs){
let object=super.createObject(type);
this.objects.set(object.id,object);
/* do things with otherargs */
return object.id;
}
}
/* Method to test function. In test class */
templateObjects(){
let container=this.getContainer();
console.log("proto: "+JSON.stringify(Object.getPrototypeOf(container)));
let tt=App.createObjectType("template1","",[{name:"attr0",value:1},{name:"attr1",value:2},{name:"attr2",value:3}]);
let ut=App.createObjectType("test","template1",[{name:"attr3",value:66}]);
container.addObjectType(tt);
container.addObjectType(ut);
let o0=container.createObject("template1");
console.log("Object: "+JSON.stringify(o0));
let o1=container.createObject("test");
console.log("Object: "+JSON.stringify(o1));
}
当我现在尝试从子类创建基于模板的对象时,超类代码就到了这一点:
if (this.objecttypes[i].template) {
object = this.createObject(this.objecttypes[i].template);
object.type = type;
}
'this.createObject(...)' 调用导致调用子类的 createObject 方法,从而返回一个数字键,并且尝试为其分配类型失败。
我知道我可以例如重命名子类中的方法以避免问题,我可以发送 class object(“this”)作为参数或其他棘手的东西。
但是有没有更直接、更惯用的方法来解决这个问题?
this
是指 object,而不是 class。 在这种情况下,它是正常使用的B
实例(即使在A
中的代码中——只有一个对象)。 由于 object 的createObject
属性来自B
,这就是您从this.createObject
获得的(无论该代码出现在何处)。
但是还有一个更根本的问题:
当您子类化某些东西时,您是在说它是您子类化的东西的更专业的版本。 也就是说, B
是专门A
。 这意味着B
是A
。 A
有一个特定的合同,例如它从它的createObject
方法返回一个 object。 通过更改B
中的返回类型,您将违反该合同。 B
不再是A
,它是类似于A
的东西,除了createObject
。
所以我建议不要这样做,因为它违反了子类化规则之一。
您可以从A
中的代码调用A
的createObject
版本,如下所示:
object = A.prototype.createObject.call(this, this.objecttypes[i].template);
但我强烈建议您不要这样做。 :-) 相反,不要让B
违反A
的合同。 对您在B
中所做的事情使用不同的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.