web-dev-qa-db-ja.com

タイプスクリプトのスーパークラスからオーバーライドされたメソッドを呼び出す

スーパークラスコンストラクターからオーバーライドされたメソッドを呼び出すと、サブクラスプロパティの値を正しく取得できません。

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
    }
}

TypeScriptの関数を正しくオーバーライドする方法を知りたいです。

42
Sency

実行順序は次のとおりです。

  1. Aのコンストラクター
  2. Bのコンストラクター

割り当ては、Bのコンストラクター_superが呼び出された後、Aのコンストラクターで行われます。

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のコンストラクターに文字列を渡してなんとかする...多くの可能性があります。

17
David Sherret

キーは、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"

ここで試してみてください

70
Flavien Volken

スーパークラスでサブクラスから関数を呼び出す場合、最もクリーンな方法は抽象パターンを定義することです。この方法では、メソッドがどこかに存在し、サブクラスでオーバーライドする必要があることが明示的にわかります。

これは一例です。通常、サブインスタンスはまだ初期化されていないため、コンストラクター内でサブメソッドを呼び出しません…(質問の例に「未定義」がある理由)

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();

テスト ここ

そして、@ 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();

試してみてください ここ

8
Flavien Volken