class A {
A(int value);
}
class B extends A{
final int foo;
B.one(this.foo) : super(foo); // Works
B.two(int foo) : foo = foo, super(this.foo); // Doesn't work
}
在B.one
中,我可以很容易地将foo
的值传递给super
,但在B.two
中,我不能这样做。在这两种情况下,字段foo
都是在调用super
之前分配的,在一种情况下它可以工作,而在另一种情况下它会失败。因此,问题是在构造函数中创建字段的位置。
2条答案
按热度按时间cwxwcias1#
Dart分两个阶段构造对象:先由外向内然后由内向外
初始化器列表由外向内执行(从派生类到基类)。在此之后,对象的成员应该被初始化,对象被认为是“构造”的,并且
this
存在。(这就是为什么你不能在初始化器列表中以有意义的方式使用this
;(从技术上讲,直接成员初始化发生在初始化器列表之前,但为了简单起见,我将它们集中在一起。)然后构造函数体由内而外地执行(从基类到派生类)。
这种方法可以保证在基类构造函数体执行时初始化对象的所有成员,从而允许在构造函数体中进行虚拟分派。(相比之下,C纯粹由内而外地构造对象,并且不允许在构造函数和析构函数中使用虚拟分派。或者与Python相反,Python中的类主要定义自己的构造顺序,并且类负责确保构造函数执行的任何虚函数调用都是安全的。
如果没有这种方法,Dart构造函数体在执行虚函数时要么不能保证安全(Java方法),要么必须禁止虚拟分派(C方法)。
这种方法的一个结果是
final
变量可以通过初始化器列表初始化,但不能通过构造函数体初始化:当构造函数体执行时,所有成员变量(不是late
并且不能为空)都应该已经初始化。另见:
wkyowqbh2#
问题是您不能将
this
或其属性传递给super
。this
仅在示例方法或生成构造函数的上下文中定义。请参阅:https://dart.dev/tools/diagnostic-messages#invalid_reference_to_this。
这工程
在
B.one
中,您将作为属性foo
传递给superfoo
,但在B.two
中,您将从two
上的参数传递foo
看看这个