【问题标题】:Difference between assigning the values in parameter list and initializer list在参数列表和初始化列表中赋值的区别
【发布时间】:2020-11-28 11:01:39
【问题描述】:
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 中,我不能这样做。在这两种情况下,在调用super 之前分配了字段foo,在一种情况下它可以工作,而在另一种情况下它会失败。所以,问题是在构造函数中创建字段的时间点。

【问题讨论】:

    标签: dart


    【解决方案1】:

    Dart 分两个阶段构造对象:首先由外向内,然后由内向外。

    初始化器列表由外向内执行(从派生类到基类)。完成后,对象的成员应该被初始化,对象被认为是“构造的”,this 存在。 (这就是为什么你不能在初始化列表中以有意义的方式使用this;它还不存在。)(技术上直接成员初始化发生在初始化列表之前,但为了简单起见,我将它们混为一谈。)

    然后由内向外执行构造函数体(从基类到派生类)。

    这种方法保证在基类构造函数体执行时,所有对象的成员都被初始化,允许在构造函数体中发生虚拟调度。 (相比之下,C++ 完全由内而外地构造对象,并且不允许在构造函数和析构函数中进行虚拟调度。或者与 Java 相比,IIRC 类主要定义自己的构造顺序,并且类负责确保执行任何虚拟函数调用构造函数是安全的。)

    如果没有这种方法,Dart 构造函数体要么不能保证执行虚函数(Java 方法)时的安全性,要么必须禁止虚拟调度(C++ 方法)。

    这种方法的一个结果是final 变量可以由初始化列表初始化,但不能由构造函数主体初始化:当构造函数主体执行时,所有成员变量(不是late 且不可为空)预计已经初始化。

    另见:

    【讨论】:

      【解决方案2】:

      问题是您不能将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 传递给超级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
      }
      

      【讨论】:

      • 引用你的第一行'you can't pass this or ...',你认为fooB.one构造函数中传递给super实际上是一个类属性吗?
      • 它是创建对象的属性。
      • 所以,在B.one 中,我将foo 属性(已创建)传递给super,在B.two 中,我还将相同的foo 属性(已创建)传递给@ 987654341@。有什么区别?
      • B.one 中,您将由(初始化形式)参数this.foo 引入的变量 foo 的值传递给超级构造函数,而不是@987654345 @。 this.foo 参数做了两件事:它将foo 字段初始化为存储参数值的值,并引入了一个名为foo 的最终变量,该变量绑定到初始化列表范围内的相同值。这就是您所指的变量。
      • @Locked 不确定您更新的代码如何回答问题。在B.two 中,您只是将foo 的传递值传递给super,而不是我想要传递的实例字段foo 的值。
      猜你喜欢
      • 1970-01-01
      • 2018-10-29
      • 1970-01-01
      • 2012-03-11
      • 1970-01-01
      • 1970-01-01
      • 2015-01-19
      • 1970-01-01
      • 2019-07-29
      相关资源
      最近更新 更多