我对类实例变量覆盖的规则感到困惑
class S0 {
num a;
S0(this.a) {
print("in S0 :$a");
}
}
class S1 extends S0 {
num a;
S1(this.a) : super(a + 1) {
print("in S1 :$a");
}
}
main() {
var b = S1(123);
print(b.a);
}
以上是我的代码。我希望它能打印:
在S0中:124
在S1中:123
123
但是结果是:
在S0中:123
在S1中:123
123
为什么?谢谢!
答案 0 :(得分:2)
在Dart中,instance variables implicitly create getter and (for non-final
members) setter functions。也就是说,S0
的接口是隐式的:
class S0 {
num get a;
set a(num value);
S0(num a);
}
从这个角度看,应该更清楚的是,当S0
尝试访问a
时,它使用其getter方法,在这种情况下,该方法被S1
覆盖,因此总是返回{ {1}}的值。
施工顺序也很重要。构造派生的S1
类的实例将执行:
S1
)的初始化列表。S1
)中的初始化列表。S0
)中的构造函数主体。S0
)的构造函数主体。在第2步之后,该对象被认为已足够构造以进行虚拟调度工作(即,要调用派生类中的重写)。 (这与C ++等语言不同,在C ++中,对象是纯粹从基类构造到派生类的,并且不允许在构造函数中进行虚拟调度,以防止在未构造的对象上调用方法。)
答案 1 :(得分:1)
因为在构造函数主体中允许访问此(及其成员)。因此,getter和setter是在执行构造函数之前生成的。
所有实例变量都会生成一个隐式的getter方法。非最终实例变量也会生成隐式setter方法。
,并在Dart Programming Language Specification第10.8.1章继承和覆盖中进行了描述
实例变量从不相互替代。的吸气剂和二传手 实例变量。
因此,当您在S0类中调用this.a时,它已被子类S1覆盖;