首页 > 解决方案 > 后期实例字段是否在构造函数中延迟初始化?

问题描述

我了解late初始化程序,即直接具有初始化分配的声明,是懒惰地执行的:

class Foo {
  late final word = calculateWord(); // Will be initialized lazily.
  late final sentence; // Will not be initialized lazily.

  void init() {
    sentence = calculateSentence(); // This is immediately executed, i.e. before sentence is accessed.
  }
}

但是,我想知道的是该行为如何映射到构造函数。我会假设该变量在构造函数中被延迟初始化,因为实例字段随后与那些直接通过赋值具有初始值设定项的字段同时被赋值。

但是,我还假设构造函数主体不会延迟初始化late实例字段。


那么以下哪些成员被延迟初始化(如果有的话)?

class Baz {
  Baz(
    // Implicit assignment by the caller.
    this.assignmentInConstructor,
  ) : assignmentInInitializerList = calculate() {
    assignmentInConstructorBody = calculate();
  }


  late final int assignmentInConstructor; // I expect this to be lazily initialized.

  late final int assignmentInInitializerList; // I expect this to also be lazily initialized.

  late final int assignmentInConstructorBody; // I expect this to not be lazily initialized.
}

标签: flutterdart

解决方案


没有一个是懒惰的

只有在声明late发生赋值时,修改的字段才会变得懒惰。

这也意味着以下情况是正确的:

void main() {
  late final value1 = calculate(); // This is initialized lazily.

  late final value2;value2 = calculate(); // This is not initialized lazily.
}

只有通过添加;value2,我将赋值与声明分开,这使它不再懒惰。

实例字段

因此,在构造函数中任何位置初始化的所有实例字段都不会被延迟初始化。相反,它们在被访问之前被初始化。

演示

void main() {
  // Construct the object first.
  final baz = Baz(calculate('assignmentInConstructor'));

  // Call access to access the late variables and initialize them if they are lazy.
  baz.access();
}

class Baz {
  Baz(
    // Implicit assignment by the caller.
    this.assignmentInConstructor,
  ) : assignmentInInitializerList = calculate('assignmentInInitializerList') {
    assignmentInConstructorBody = calculate('assignmentInConstructorBody');
  }

  late final int
      assignmentInConstructor; // I expect this to be lazily initialized.

  late final int
      assignmentInInitializerList; // I expect this to also be lazily initialized.

  late final int
      assignmentInConstructorBody; // I expect this to not be lazily initialized.

  void access() {
    print('access');
    print('$assignmentInConstructor'
        '$assignmentInInitializerList'
        '$assignmentInConstructorBody');
  }
}

int calculate(String message) {
  print('calcuate $message');
  return 0;
}

执行main产生以下输出:

calcuate assignmentInConstructor
calcuate assignmentInInitializerList
calcuate assignmentInConstructorBody
access
000

这意味着所有三个实例字段,无论它们在构造函数中的哪个位置被初始化,都不会被延迟初始化。它们都是在访问之前计算出来的。

您可以在此 DartPad 演示中亲自尝试。


推荐阅读