2016-08-22 78 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