[英]Typescript, static method inheritance
我正在使用打字稿,但類之間的靜態繼承有問題
任何人都可以向我解釋以下結果:
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
屬性的解決方案?
謝謝 !
理解static
和class
的關鍵是子類的構造函數繼承自超類的構造函數。 字面上地。 class
不只是在構造函數創建的實例之間設置繼承,構造函數本身也處於繼承結構中。
Foo
是Son
和Daughter
的原型。 這意味着Daughter.bar
是Foo.bar
,它是一個繼承的屬性。 但是您為Son
了自己的bar
屬性和自己的數組,因此在Son
查找bar
找到Son
自己的bar
,而不是Foo
上的bar
。 這是一個更簡單的例子:
class Foo { } class Son extends Foo { } class Daughter extends Foo { } Foo.bar = new Map([["a", "ayy"]]); console.log(Foo.bar.get("a")); // "ayy" // `Son` inherits `bar` from `Foo`: console.log(Son.bar === Foo.bar); // true, same Map object console.log(Son.bar.get("a")); // "ayy" // So does `Daughter` -- for now console.log(Daughter.bar === Foo.bar); // true, same Map object console.log(Daughter.bar.get("a")); // "ayy" // Retroactively giving `Son` its own static `bar` Son.bar = new Map(); console.log(Son.bar === Foo.bar); // false, different Map objects console.log(Son.bar.get("a")); // undefined
這就是為什么當您查看Foo.bar
和Daughter.bar
時會看到["Hello", "Both ?"]
Foo.bar
:這是同一個bar
,指向同一個數組。 但是您只能在Son.bar
上看到["World"]
,因為它是指向不同數組的不同bar
。
為了將它們分開,您可能希望為每個構造函數提供自己的bar
,盡管您可以按照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);
如果你剛接觸它,這是一件非常令人驚訝的事情,但是你的三個類在內存中看起來像這樣:
+−−>Function.prototype +−−−−−−−−−−−−−−−+ | Foo−−−−−−−−−−−−−−−−−−+−+−>| (function) | | / / +−−−−−−−−−−−−−−−+ | | | | [[Prototype]] |−−+ +−−−−−−−−−−−+ | | | bar |−−−−−−−−−>| (array) | | | | addBar, etc. | +−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−+ | length: 2 | | | | 0: Hello | | +−−−−−−−−−−−−−+ | 1: Both ? | | | +−−−−−−−−−−−+ +−−−−−−−−−−−−+ | | | +−−−−−−−−−−−−−−−+ | | | (function) | | | +−−−−−−−−−−−−−−−+ | | Daughter−−−−−>| [[Prototype]] |−−+ | +−−−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−+ | | (function) | | +−−−−−−−−−−−−−−−+ | Son−−−−−−−−−−>| [[Prototype]] |−−−−−+ +−−−−−−−−−−−+ | bar |−−−−−−−−−>| (array) | +−−−−−−−−−−−−−−−+ +−−−−−−−−−−−+ | length: 1 | | 0: World | +−−−−−−−−−−−+
@TJCrowder 在此線程中的回答中找到了對 OP 代碼中行為的非常詳細的解釋。
為了避免重新定義靜態成員的需要,您可以采用以下方法:
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 ?');
( 操場上的代碼)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.