2016-08-22 69 views
4

请对这个代码来看看:打字稿多态性

class Greeter { 
    greeting: string; 
    constructor(message: string) { 
     this.greeting = message; 
    } 
    greet() { 
     return "Hello, " + this.greeting; 
    } 
} 

class Ge extends Greeter { 
    constructor(message: string) { 
     super(message); 
    } 
    greet() { 
     return "walla " + super.greet(); 
    } 
} 

let greeter = new Ge("world"); 

console.log(greeter.greet()); // walla Hello, world 
console.log((<Greeter> greeter).greet()); // walla Hello, world 

我希望第二个日志打印Hello, world。 看着编译好的Javascript代码,我看到了完全相同的命令,所以这并不令人意外。

真正的问题是,您如何将greeter投射到其扩展类?

回答

3

您已经将greeter投射到它的父类。

类中的重写方法在转换为其父类时不会改变行为。

+0

那么我会如何实现呢? – johni

3

JS(和TS)中的方法附加到附加到每个实例(类似虚拟方法表的东西)的原型。当你调用一个方法时,实际的函数是从实例的原型链中检索的,而不是已知类型的对象。我知道的最接近的是C++中的virtual方法。

在代码:

let greeter = new Ge('world'); 
// You expect: 
Greeter.prototype.greet.call(greeter); 
// JS actually does: 
greeter.prototype.greet.call(greeter); 
+0

那我该怎么做呢? – johni

+1

如果你想调用子方法的super方法,你可以直接使用'Class.prototype.method'语法和[Function's'call'方法](https://developer.mozilla.org/en-US /文档/网络/的JavaScript /参考/ Global_Objects /功能/调用)。 – ssube

0

仅铸造告诉编译器把一个变量,如果它有它的价值的特定类型。

投射对输出的JavaScript代码没有影响。它有时会允许编译器在它认为您将类型A视为类型B时不会发出错误,但JavaScript代码没有类型的概念。

您的类实例具有一个名为greet的属性,它隐藏了该对象原型上的属性(基类问候函数)。所以被调用的函数总是继承线上最低的那个函数。

您可能需要查看输出代码,然后应用您所了解的原型继承以了解该代码。

2

我想你误解了铸造。这不是“转换成”,而是更多的“解释为”。它基本上给了编译器一个提示,至少他正在处理的类型/接口,因此有很多属性和方法可用。它并没有说任何关于这些方法的实现,只有他们的签名(这些类型进来,这种类型出来)

+0

我明白你的观点。但是这有点误导你,你不同意吗? – johni

+2

不,为什么?这就是如何投射,而不仅仅是在JS中。 – Thomas

+0

Sry,我正在打电话,不能正常上传代码:** Greeter.prototype.greet.call(greeter)**从** Greeter **类中调用方法** greet **实例**欢迎** – Thomas