我认为这是有充分理由的,但对我来说似乎很奇怪。请将以下代码作为问题的示例。
class Foo {
constructor(referenceMethod: () => void) {
}
}
class Bar extends Foo {
TestProperty: string = "boo";
constructor() {
super(this.ReferenceMethod);
}
ReferenceMethod() {
}
}
这会产生编译器错误
'this'无法在当前位置引用。
如果我们初始化构造函数中的TestProperty
,编译器很高兴并且世界按预期旋转,当然如果我们不将referenceMethod的引用传递给超级调用,我们可以在外面设置TestProperty构造函数很好。
然而,我只是不明白为什么一起做这两件事会导致问题。如果有人能够对此有所了解,那将有助于我的理解。
答案 0 :(得分:5)
Typescript language specification中的8.3.2:
构造函数体中的第一个语句必须是超级调用 如果以下两个都是真的: 1.包含类是派生类 2.构造函数声明参数属性或包含类声明 具有初始化程序的实例成员变量。
示例中的包含类声明了一个名为TestProperty
的变量,该变量使用初始值设定项:
TestProperty: string = "boo";
您看到错误的原因是编译器要求constructor
的第一行是super
的调用,给定您班级的当前布局(#2来自上面的语言规范)。因此,这意味着当您开始引用类的属性(例如TestProperty
)时,类未完全初始化。虽然ReferenceMethod
将被初始化并且可用,但成员变量仍然不会,这可能会破坏您班级中的其他功能。
虽然语言作者可以生成可以避免此问题的工作代码,但当它以您找到的方式工作时,它显然更容易且更一致。
作为替代方案,您可以尝试添加一个initialize
方法,该方法在构造函数完全初始化类后执行相同的逻辑。这无疑是第二步,但它适用于TypeScript。但是,请小心确保在构造函数初始化成员变量后>>初始化为。
答案 1 :(得分:0)
似乎Foo
和Bar
有不同的行为。 Foo
接受回调作为其构造函数,但Bar
将回调作为实例方法。你的真实用例是什么?也许Bar
应该撰写(包含)Foo
而不是扩展它。
或者,您可以修改Foo
的行为以接受可选回调,还可以定义用作默认值的可覆盖实例方法。然后派生类可以忽略回调参数,而只是覆盖实例方法。
选项1:作文
class Foo {
constructor(referenceMethod: () => void) {
}
}
class Bar {
TestProperty: string = "boo";
foo: Foo;
constructor() {
this.foo = new Foo(this.ReferenceMethod);
}
ReferenceMethod() {
}
}
选项2:参考方法为可选的arg和可覆盖的
class Foo {
constructor(referenceMethod?: () => void) {
if (referenceMethod) {
this.ReferenceMethod = referenceMethod;
}
}
ReferenceMethod():void {}
}
class Bar {
TestProperty: string = "boo";
constructor() {
}
ReferenceMethod():void {
}
}
答案 2 :(得分:0)
如果某人处理此错误,在构造函数中使用oci.dll
或private
修饰符时也会发生这种情况。
尝试:
public
而不是:
constructor(x : number) {
... super call with this reference
this.x = x;
}
private x : number;