2015-06-13 70 views
16

當我從超類構造函數調用重寫的方法時,我無法正確獲取子類屬性的值。調用打字稿中超類的重寫方法

例如

class A 
{ 
    constructor() 
    { 
     this.MyvirtualMethod(); 
    } 

    protected MyvirtualMethod(): void 
    { 

    } 
} 

class B extends A 
{ 
    private testString: string = "Test String"; 

    public MyvirtualMethod(): void 
    { 
     alert(this.testString); // This becomes undefined 
    } 
} 

我想知道如何正確地重寫打字稿功能。

+5

在調用構造函數的虛方法被認爲是在任何OOP語言不好的做法:https://google.com/search?q=virtual+method+in+constructor –

回答

11

執行順序是:

  1. A的構造
  2. B的構造在B發生

分配的構造後A的constructor- _super都具有一個被稱爲:

function B() { 
    _super.apply(this, arguments); // MyvirtualMethod called in here 
    this.testString = "Test String"; // testString assigned here 
} 

所以會發生以下情況:

var b = new B();  // undefined 
b.MyvirtualMethod(); // "Test String" 

你需要改變你的代碼來處理這個問題。例如,通過在B的構造函數中調用this.MyvirtualMethod(),創建一個工廠方法來創建該對象,然後執行該函數,或者通過將該字符串傳遞到A的構造函數中,並以某種方式工作......有很多可能性。

+0

OO啊.. 得到它了。謝謝。我認爲屬性在構造函數之前初始化。 – Sency

+0

在'new.target'可能有用的情況下,我們不在這裏嗎? – GameAlchemist

24

關鍵是使用super.methodName()調用父類的方法;

class A { 
    // A protected method 
    protected doStuff() 
    { 
     alert("Called from A"); 
    } 

    // Expose the protected method as a public function 
    public callDoStuff() 
    { 
     this.doStuff(); 
    } 
} 

class B extends A { 

    // Override the protected method 
    protected doStuff() 
    { 
     // If we want we can still explicitly call the initial method 
     super.doStuff(); 
     alert("Called from B"); 
    } 
} 

var a = new A(); 
a.callDoStuff(); // Will only alert "Called from A" 

var b = new B() 
b.callDoStuff(); // Will alert "Called from A" then "Called from B" 

Try it here

5

如果你想有一個超類中調用子類中的功能,最徹底的方法是定義一個抽象的圖案,以這種方式,你明確地知道方法的某處存在,必須重寫由一個子類。

這是作爲一個例子,通常你不會在構造函數中調用子方法,子實例尚未初始化......(爲什麼你有你的問題的例子是「不確定」)

abstract class A { 
    // The abstract method the subclass will have to call 
    protected abstract doStuff():void; 

    constructor(){ 
    alert("Super class A constructed, calling now 'doStuff'") 
    this.doStuff(); 
    } 
} 

class B extends A{ 

    // Define here the abstract method 
    protected doStuff() 
    { 
     alert("Submethod called"); 
    } 
} 

var b = new B(); 

測試它Here

如果@Max你真的想要避免在任何地方實現抽象方法,只是擺脫它。我不推薦這種方法,因爲你可能會忘記你重寫了這個方法。

abstract class A { 
    constructor() { 
     alert("Super class A constructed, calling now 'doStuff'") 
     this.doStuff(); 
    } 

    // The fallback method the subclass will call if not overridden 
    protected doStuff(): void { 
     alert("Default doStuff"); 
    }; 
} 

class B extends A { 
    // Override doStuff() 
    protected doStuff() { 
     alert("Submethod called"); 
    } 
} 

class C extends A { 
    // No doStuff() overriding, fallback on A.doStuff() 
} 

var b = new B(); 
var c = new C(); 

試試吧Here

+0

此解決方案將強制在每個子類中定義此方法,即使它不是必需的。 – Max

+0

@Max這是摘要的唯一目的。我爲你解答了一個例子 –

相關問題