スーパークラスコンストラクターからオーバーライドされたメソッドを呼び出すと、サブクラスプロパティの値を正しく取得できません。
例
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の関数を正しくオーバーライドする方法を知りたいです。
実行順序は次のとおりです。
A
のコンストラクター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
のコンストラクターに文字列を渡してなんとかする...多くの可能性があります。
キーは、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"
スーパークラスでサブクラスから関数を呼び出す場合、最もクリーンな方法は抽象パターンを定義することです。この方法では、メソッドがどこかに存在し、サブクラスでオーバーライドする必要があることが明示的にわかります。
これは一例です。通常、サブインスタンスはまだ初期化されていないため、コンストラクター内でサブメソッドを呼び出しません…(質問の例に「未定義」がある理由)
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();
試してみてください ここ