打字稿,静态方法继承
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
上的那个。这是发生这种情况的一个更简单的例子:
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 ?"]
的原因:它们是相同的 bar
,指向相同的数组。但是您只能在 Son.bar
上看到 ["World"]
,因为它是指向不同数组的不同 bar
。
要将它们分开,您可能希望为每个构造函数提供其自己的 bar
,尽管您 可以 使用 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 |
+−−−−−−−−−−−+
@T.J.Crowder 在 中找到了对 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 ?');
我正在使用打字稿,我在 类
之间的静态继承有问题任何人都可以向我解释以下结果:
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
上的那个。这是发生这种情况的一个更简单的例子:
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 ?"]
的原因:它们是相同的 bar
,指向相同的数组。但是您只能在 Son.bar
上看到 ["World"]
,因为它是指向不同数组的不同 bar
。
要将它们分开,您可能希望为每个构造函数提供其自己的 bar
,尽管您 可以 使用 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 | +−−−−−−−−−−−+
@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 ?');