web-dev-qa-db-ja.com

Typescript、静的メソッドの継承

TypeScriptを使用していますが、クラス間の静的継承に問題があります

誰かが私に次の結果を説明できますか?

class Foo {
    protected static bar: string[] = [];

    public static addBar(bar: string) {
        this.bar.Push(bar);
    }

    public static logBar() {
        console.log(this.bar);
    }
}

class Son extends Foo {
    protected static bar: string[] = [];
}

class Daughter extends Foo {}

Foo.addBar('Hello');
Son.addBar('World');
Daughter.addBar('Both ?');
Foo.logBar();
Son.logBar();
Daughter.logBar();

現在の結果:

[ 'Hello', 'Both ?' ]
[ 'World' ]
[ 'Hello', 'Both ?' ]

でも私はしたい :

[ 'Hello' ]
[ 'World' ]
[ 'Both ?' ]

静的barプロパティを再宣言せずに解決策はありますか?

よろしくお願いします!

10
vincent_chapron

OPコードの動作の非常に詳細な説明は、@ T.J.Crowderの このスレッドでの回答 にあります。

静的メンバーを再定義する必要を回避するには、次の方法を使用できます。

class Foo {
    private static bar = new Map<string, string[]>();

    public static addBar(bar: string) {
        let list: string[];

        if (this.bar.has(this.name)) {
            list = this.bar.get(this.name);
        } else {
            list = [];
            this.bar.set(this.name, list);
        }

        list.Push(bar);
    }

    public static logBar() {
        console.log(this.bar.get(this.name));
    }
}

class Son extends Foo {}

class Daughter extends Foo {}

Foo.addBar('Hello');
Son.addBar('World');
Daughter.addBar('Both ?');

遊び場のコード

9
Nitzan Tomer

staticclassについて理解しておくべき重要なことは、サブクラスのコンストラクター関数がスーパークラスのコンストラクター関数から継承されることです。文字通り。 classjustコンストラクターによって作成されたインスタンス間の継承を設定しません。コンストラクターthemselvesも継承構造。

Fooは、SonおよびDaughterのプロトタイプです。つまり、Daughter.barisFoo.bar、それは継承されたプロパティです。しかし、Sonownbarプロパティを独自の配列で指定したため、Fooとのリンクが壊れています。

そのため、["Hello", "Both ?"]を見るとFoo.barおよびDaughter.bar:同じbarで、同じ配列を指します。しかし、あなただけが["World"] オン Son.bar、それは別の配列を指す別のbarだからです。

それらを分離するには、おそらく各コンストラクタに独自のbarを指定する必要がありますが、couldは、 Nitzan Tomerの提案Map


物事がどのように構成されているかについてもう少し詳しく。それはこのような少しです:

const Foo = {};
Foo.bar = [];
const Son = Object.create(Foo);
Son.bar = []; // Overriding Foo's bar
const Daughter = Object.create(Foo);
Foo.bar.Push("Hello");
Son.bar.Push("World");
Daughter.bar.Push("Both ?");
console.log(Foo.bar);
console.log(Son.bar);
console.log(Daughter.bar);

これは、新鮮なものになると非常に驚くべきことですが、3つのクラスは次のように見えます。

 +-> Function.prototype 
 + −−−−−−−−−−−−−−− + | 
 Foo −−−−−−−−− −−−−−−−−− + − + −> | (機能)| | 
// + −−−−−−−−−−−−−−− + | 
 | | | [[プロトタイプ]] |-+ + −−−−−−−−−−− + 
 | | |バー| −−−−−−−−−> | (配列)| 
 | | | addBarなど| + −−−−−−−−−−− + 
 | | + −−−−−−−−−−−−−−− + |長さ:2 | 
 | | | 0:こんにちは| 
 | + −−−−−−−−−−−−− + | 1:両方? | 
 | | + −−−−−−−−−−− + 
 + −−−−−−−−−−−− + | 
 | | 
 + −−−−−−−−−−−−−−− + | | 
 | (機能)| | | 
 + −−−−−−−−−−−−−−− + | | 
娘---------> | [[プロトタイプ]] |-+ | 
 + −−−−−−−−−−−−−−− + | 
 | 
 + −−−−− −−−−−−−−−− + | 
 | (機能)| | 
 + −−−−−−−−−−−−−−− + | 
息子-------------------> | [[プロトタイプ]] | −−−−− + + −−−−−−−−−−− + 
 |バー| −−−−−−−−−> | (配列)| 
 + −−−−−−−−−−−−−−−− + + −−−−−−−−−−− + 
 |長さ:1 | 
 | 0:世界| 
 + −−−−−−−−−−− + 
14
T.J. Crowder