dart 在参数列表和初始化列表中赋值的区别

cwdobuhd  于 2023-09-28  发布在  其他
关注(0)|答案(2)|浏览(120)
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之前分配的,在一种情况下它可以工作,而在另一种情况下它会失败。因此,问题是在构造函数中创建字段的位置。

cwxwcias

cwxwcias1#

Dart分两个阶段构造对象:先由外向内然后由内向外
初始化器列表由外向内执行(从派生类到基类)。在此之后,对象的成员应该被初始化,对象被认为是“构造”的,并且this存在。(这就是为什么你不能在初始化器列表中以有意义的方式使用this;(从技术上讲,直接成员初始化发生在初始化器列表之前,但为了简单起见,我将它们集中在一起。)
然后构造函数体由内而外地执行(从基类到派生类)。
这种方法可以保证在基类构造函数体执行时初始化对象的所有成员,从而允许在构造函数体中进行虚拟分派。(相比之下,C纯粹由内而外地构造对象,并且不允许在构造函数和析构函数中使用虚拟分派。或者与Python相反,Python中的类主要定义自己的构造顺序,并且类负责确保构造函数执行的任何虚函数调用都是安全的。
如果没有这种方法,Dart构造函数体在执行虚函数时要么不能保证安全(Java方法),要么必须禁止虚拟分派(C
方法)。
这种方法的一个结果是final变量可以通过初始化器列表初始化,但不能通过构造函数体初始化:当构造函数体执行时,所有成员变量(不是late并且不能为空)都应该已经初始化。
另见:

wkyowqbh

wkyowqbh2#

问题是您不能将this或其属性传递给super
this仅在示例方法或生成构造函数的上下文中定义。
请参阅:https://dart.dev/tools/diagnostic-messages#invalid_reference_to_this。
这工程

class B extends A{
  final int foo;

  B.one(this.foo) : super(foo);

  B.two(int foo) : foo = foo, super(foo); 
}

B.one中,您将作为属性foo传递给super foo,但在B.two中,您将从two上的参数传递foo
看看这个

class A {
  A(int value) {
    print(value);
  }
}

class B extends A {
  final int foo;

  B.one(this.foo) : super(foo);

  B.two(int foo): foo = 5, super(foo);
}

main() {
 B b = B.two(100); //Prints 100;
 print(b.foo); //Prints 5
}

相关问题