我们假设我有一个Base
类和一个Test
类,它来自Base
。 Base
类有一个受保护的成员,让我们说它是一个存储字符串字典的对象。我希望在Test
类中覆盖该字典,但不知何故,它不能按预期工作(至少在我的生产代码中,以及我在JS Bin上测试时):
type ConstantsDict = { [key: string]: string }
abstract class Base {
protected readonly _constants: ConstantsDict = {
FOO: 'bar'
}
protected get _magicStringFoo(): string {
return `Base: ${this._constants.FOO}`;
}
constructor() {
// The magic constant FOO is incorrect when invoked in Test
alert(this._magicStringFoo);
}
}
class Test extends Base {
// Overwrite inherited member
protected readonly _constants = {
FOO: 'lorem ipsum dolor sit amet'
}
// Overwrite inherited getter
protected get _magicStringFoo(): string {
return `Test: ${this._constants.FOO}`;
}
// Let's give Test it's own getter for the same magic constant
private get _magicStringFooPrivate(): string {
return `Test: ${this._constants.FOO}`;
}
constructor() {
super();
// The magic constant FOO is correct over here
alert(`Local magic constant FOO is: ${this._magicStringFooPrivate}`)
}
}
new Test();
代码会提醒Test: bar
而不是Test: lorem ipsum dolor sit amet
。好消息是从Base
类继承的受保护的getter正在Test
中被覆盖,但不知怎的,this
引用仍指向不正确的类。
答案 0 :(得分:1)
这是由构造函数如何交互引起的排序问题。
以下是基于代码的构造函数(为了便于使用而删除了所有其他代码)。
我在实例化新的Test
// 3
function Base() {
// 4
this._constants = {
// 5
FOO: 'bar'
// 6
};
// 7 (at this point, FOO is 'bar')
alert(this._magicStringFoo);
}
// 1
function Test() {
// 2
var _this = _super.call(this) || this; // <-- GO TO SUPER CLASS CONSTRUCTOR
// 8
_this._constants = {
// 9
FOO: 'lorem ipsum dolor sit amet'
// 10
};
// 11
alert("Local magic constant FOO is: " + _this._magicStringFooPrivate);
//12
return _this;
}
你可以在这里看到为什么子类似乎有错误的值 - 它只是没有机会在那时覆盖基类值。
我建议的修复方法是将值传递给超类构造函数。
这是一个简单的版本:
type ConstantsDict = { [key: string]: string }
abstract class Base {
constructor(protected magicStringFoo: string) {
// The magic constant FOO is incorrect when invoked in Test
alert(this.magicStringFoo);
}
}
class Test extends Base {
constructor() {
super('Test: lorem ipsum dolor sit amet');
}
}
new Test();
我已将测试字符串传递给那里,但您可以传递FOO
常量或任何您需要的值。这解决了任何订购问题。