打字稿覆盖类的方法,这
我有这两个打字稿类:打字稿覆盖类的方法,这
class Base {
value: string;
lambdaExample =() => {
this.value = 'one';
}
methodExample() {
this.value = 'two';
}
}
class Child extends Base {
lambdaExample =() => {
super.lambdaExample(); // Error, because I've overwritten (instead of overridden) the method
this.value = 'three'; // ok
}
methodExample() => {
super.methodExample(); // ok
this.value = 'four'; // Error: this refers to window, not to the actual this
}
}
我怎样写我的方法,这样的方式this
引用是可靠的,和我可以重写方法和调用它们父类?
实际上,在Microsoft's Git Wiki上处理这个问题的方法很好看。它基本上归结为:
- 如果您关心继承,每次从不同的上下文调用方法时绑定或包装该方法。
- 将方法转换为包含函数的属性(如果不包含)。
在实际的维基中还有很多规定,我真的建议你阅读整个事情。
编辑
包装的一个例子:
鉴于类
class SomeClass {
public someProp: string = "Hello World";
public someMethod() {
console.log(this.someProp);
}
}
如果你要调用someMethod
从(例如)单击处理 - someEl.onclick = instanceOfMyClass.someMethod;
- 一个例外(假设window
没有财产someProp
)。
您可以通过函数或者结合instanceOfMyClass
(不是类型安全的,不ES6兼容)或者通过手动包装它(实际上什么绑定是干什么的,反正)规避这样的:
someEl.onclick = function() {
someInstanceOfMyClass.someMethod();
};
这是一个小有点冗长和迂腐,但通过调用someMethod
作为someInstanceOfMyClass
的属性,而不是将它传递给事件处理程序(将其变成window
的属性),则确保this
始终是MyClass
的实例。
我对包装方法略有不清楚。会有这样的工作吗? 'class Child {methodExample(){var wrap =()=> {super.methodExample()};包(); }' – Jorn
所以包装类似于绑定,因为每次从不同的上下文调用函数时都会这样做。例如,给定class class MyClass {public someMethod(){console.log(this); }}''从另一个上下文中获取'this'作为'MyClass'的一个实例,你可以这样调用它:'(()=> {instanceOfMyClass.someMethod()})()'。重要的是,我们将方法称为'instanceOfMyClass'的属性,而不是直接传递它(从而更改其上下文)。 –
你对错误原因的假设是错误的,我认为这是你问题的原因......至少据我了解。
lambdaExample =() => {
this.value = 'one';
}
此线,例如是定义上Base
一个属性,而不是一个方法,并且不能重写的属性。您在Base
中定义的唯一实例方法是methodExample
。
在Child
中,您正在为lambaExample
分配一个新变量。您拨打super.lambaExample()
失败,因为只能通过super()
访问方法;访问属性通过this
完成。您的Child
类中的methodExample
对我来说显示为语法错误。
请注意,您仍然可以在覆盖的lambaExample
属性中调用超级Child
,但只能在方法上调用。这工作:
lambdaExample =() => {
super.methodExample(); // Success on super.<somemethod>()
this.value = 'three';
}
我只知道的声明在一个类的实例方法的一种方式,如果你是与语法一致,this
作品如你所愿:
class Base {
value: string;
lambdaExample() {
this.value = 'one';
}
methodExample() {
this.value = 'two';
}
}
class Child extends Base {
lambdaExample() {
super.lambdaExample();
this.value = 'three';
}
methodExample() {
super.methodExample();
this.value = 'four';
}
}
我可以按照你的整个帖子直到最后一句:在方法的例子中,'this'不能按预期工作,正如问题中所解释的那样。在这种情况下,'super'调用起作用,但'this.value'引用是'undefined'。 – Jorn
@Jorn - 直到您将其设置为一个值时才会定义它,只有在调用lambdaExample或methodExample时才会执行此操作。 –
我已经找到了解决办法,但它的丑陋:
class Base {
someFunction =() => {
this.otherFunction();
}
protected otherFunction =() => {
// actual implementation here
}
}
class Child {
someFunction =() => {
this.otherFunction();
// additional implementation here
}
}
这样,您就可以拨打someFunction
在任何情况下,仍然使用访问的原实。
为什么downvote?我已经说过它很丑陋,但迄今为止它也是唯一的工作解决方案...... – Jorn
一些堆垛机对于回答自己的问题非常挑剔。我认为这是一个很好的自我回答,但有人可能会采取例外。 –
嗯,这不是我,即使我相信我找到了一个更好的[替代](http://stackoverflow.com/a/36918290/2788872),这会产生干净的代码。 –
的this
作用域问题可以用一个非常简单的class装饰加以解决,并且您不再需要使用难看*箭头功能语法的方法 - 或想以后再范围的问题:
function BindMethods(target: any): any {
var originalCtor = target;
var newCtor: any = function (...args) {
var c: any = function() {
// Methods are defined on prototype.
var prototype = Object.getPrototypeOf(this);
// Bind methods.
Object.keys(prototype).forEach(propertyKey => {
if (typeof this[propertyKey] === "function") {
prototype[propertyKey] = this[propertyKey].bind(this);
}
});
// Invoke original constructor.
return originalCtor.apply(this, args);
}
c.prototype = originalCtor.prototype;
return new c();
}
// Copy prototype so 'intanceof' still works.
newCtor.prototype = originalCtor.prototype;
// Overrides original constructor.
return newCtor;
}
使用它是作为捕捉它的一类一样简单(methodExample
方法被修改仅用于演示目的):
@BindMethods
class Base {
value: string;
methodExample() {
console.log(this.value);
}
}
这将确保到this
参考我总是正确的(即使有继承):
var base = new Base();
base.value = "two";
base.methodExample(); // "two"
setTimeout(base.methodExample, 20); // "two"
不幸的是,没有办法以结合方法中的一个接一个的使用方法装饰,因为需要一个实例参考。如果这是一项要求,您可以使用decorator factory传递方法的属性键进行绑定。使用方法时
*难看。
可能重复的[在打字稿中调用超类的重写方法](http://stackoverflow.com/questions/30819663/call-an-overridden-method-from-super-class-in-typescript) – smnbbrv
这是不是重复的:该问题是关于在构造函数中调用类方法,而不是关于使用类属性的重写方法。 – Jorn
@smnbbrv这个问题与此无关。 –