typescript 使用多级继承扩展基类方法(打字稿)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16839146/
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
Extending base class methods with multiple levels of inheritance (typescript)
提问by Statue26
I have 3 classes:
我有3个班级:
class A{
DoStuff(){
return "Called from A";
}
}
class B extends A {
constructor(){
super();
var baseDoStuff = super.DoStuff;
this.DoStuff = function(){
return baseDoStuff() + " and Called from B";
}
}
}
class C extends B {
constructor(){
super();
var baseDoStufffff = super.DoStuff;
this.DoStuff = function(){
return baseDoStufffff() + " and Called from C";
}
}
}
I expected class C's DoStuff() to call B's DoStuff() (which in turn would call A's).
我期望 C 类的 DoStuff() 调用 B 的 DoStuff()(后者又会调用 A 的)。
However calling DoStuff() on C only returns "Called from A and Called from C". What am I doing wrong here? Shouldn't this call B's method too?
然而,在 C 上调用 DoStuff() 只会返回“从 A 调用并从 C 调用”。我在这里做错了什么?这不应该也调用B的方法吗?
A working example of this can be found here:
可以在此处找到一个工作示例:
回答by basarat
Whenever you need to use super
Use class methodsinstead of class members:
每当您需要super
使用类方法而不是类成员时:
class A{
DoStuff(){
return "Called from A";
}
}
class B extends A {
constructor(){
super();
}
DoStuff (){
return super.DoStuff() + " and Called from B";
}
}
class C extends B {
constructor(){
super();
}
DoStuff(){
return super.DoStuff() + " and Called from C";
}
}
var c = new C();
console.log(c.DoStuff());
Try it(prints Called from A and Called from B and Called from C)
试试看(打印从 A 调用和从 B 调用和从 C 调用)
This is because super
translates to .prototype
i.e. super.DoStuff()
becomes _super.prototype.DoStuff()
and the only things available on .prototype
are class methods.
这是因为super
转换为.prototype
ie super.DoStuff()
become_super.prototype.DoStuff()
并且唯一可用的东西.prototype
是类方法。
回答by Jeffery Grajkowski
JavaScript doesn't really have methods. TypeScript tries to hide the workings of the prototype chainwith familiar notation but like all abstractions it's imperfect. The gist of the prototype chain is that when you call c.DoStuff()
it looks for DoStuff on the c instance, than the prototype (C), then its prototype (B), then its prototype (A), and then its prototype (Object).
JavaScript 并没有真正的方法。TypeScript 试图用熟悉的符号来隐藏原型链的工作,但与所有抽象一样,它并不完美。原型链的要点是,当你调用c.DoStuff()
它时,它会在 c 实例上查找 DoStuff,然后是原型 (C),然后是它的原型 (B),然后是它的原型 (A),然后是它的原型 (Object)。
That applies not just to functions but to any member you might look up. Functions aren't very special in JavaScript, which ironically is what makes them powerful.
这不仅适用于函数,也适用于您可能查找的任何成员。函数在 JavaScript 中并不是很特别,讽刺的是,这正是它们强大的原因。
Using TypeScript's syntax in your A class you're putting a function DoStuff in A's prototype. Every instance of A you call DoStuff on will look for it in the instance (and probably failing to find it there) look at the prototype and see that function you defined. So far so good.
在您的 A 类中使用 TypeScript 的语法,您将一个函数 DoStuff 放入 A 的原型中。您调用 DoStuff 的 A 的每个实例都会在实例中查找它(并且可能无法在那里找到它)查看原型并查看您定义的函数。到现在为止还挺好。
Then you defined a class B which extends A, so the prototype chain is B->A->Object. Inside the constructor of B you assign a new copy of a function to DoStuff on every single instance. (This uses a lot more memory.) So when you construct a new B and call DoStuff on it, there's a function there without ever examining the prototype. So that works.
然后你定义了一个扩展 A 的类 B,所以原型链是 B->A->Object。在 B 的构造函数中,您将一个新的函数副本分配给每个实例上的 DoStuff 。(这会使用更多的内存。)所以当你构造一个新的 B 并在它上面调用 DoStuff 时,那里有一个函数,而无需检查原型。所以这有效。
Now you define a class C extending B and the prototype chain is C->B->A->Object. Again every instance of C gets a copy of a function assigned to DoStuff. But inside that constructor we're not grabbing DoStuff from an instance of B, we're grabbing it from the prototype, and we didn't add that function directly to the prototype. Failing to find it there we go up the prototype chain to A.prototype and find a DoStuff member to use from there. That's why C has a reference to A's DoStuff.
现在你定义了一个扩展 B 的类 C,原型链是 C->B->A->Object。同样,C 的每个实例都会获得一个分配给 DoStuff 的函数的副本。但是在该构造函数中,我们不是从 B 的实例中获取 DoStuff,而是从原型中获取它,并且我们没有将该函数直接添加到原型中。在那里找不到它,我们沿着原型链向上到 A.prototype 并从那里找到要使用的 DoStuff 成员。这就是 C 引用 A 的 DoStuff 的原因。
You could make your code work as expected if you did something like this:
如果你做这样的事情,你可以让你的代码按预期工作:
class B extends A {
constructor() {
super();
}
}
B.prototype.DoStuff = function () {
return A.prototype.DoStuff() + " and Called from B";
}
But that's just being silly.
但这只是愚蠢。