Dart 中成员变量的初始化方式有什么不同吗?

2024-03-17

在 Dart 中,立即赋值与在 Java 中的构造函数中赋值有区别吗?

class Example {
    int x = 3;
}

vs

class Example {
    int x;
    Example() {
        x = 3;
    }
}

我问这个问题是因为当我使用 Flutter 并尝试将使用 setState 的函数分配给变量时,前一种方法不可能,但后一种方法可以。


在你的微不足道的情况下,这并不重要。

一般来说,可以通过以下几种方式初始化实例变量:

内联(字段初始值设定项)

class Example1 {
  T x = value;
}

优点:

  • 直接、简洁。
  • 成员将在初始化all构造函数。
  • 可以用来初始化final或不可为 null 的成员。
  • 成员在调用基类构造函数之前初始化,这在基类构造函数调用被派生类重写的成员函数时很重要。

缺点:

  • 不能依赖于构造参数。
  • 通常不能依赖this因为初始化发生在this变得有效(即不能依赖于其他实例成员)。 (一个例外是如果成员是通过声明来延迟初始化的late https://dart.dev/null-safety/understanding-null-safety#lazy-initialization。这需要启用空安全功能。)

初始化列表

class Example2 {
  T x;

  Example2() : x = value;
}

优点:

  • 可以用来初始化final或不可为 null 的成员。
  • 成员在调用基类构造函数之前初始化,这在基类构造函数调用被派生类重写的成员函数时很重要。
  • 可以利用构造参数。
  • 初始化的变量always引用成员变量,而不是构造函数参数。

缺点:

  • 如果类有多个构造函数,则需要重复初始化,或者构造函数应重定向到公共构造函数。
  • 不能依赖this因为初始化发生在this变得有效(即不能依赖于其他实例成员)。
  • 只能初始化封闭类的成员。由于初始值设定项列表是在调用基类构造函数之前执行的,因此它们无法设置基类成员。

构造函数体

class Example3 {
  T x;

  Example3() {
    x = value;
  } 
}

优点:

  • 可以利用构造参数。
  • 可用于执行更复杂的初始化,例如无法通过单个表达式初始化成员的情况。
  • Can use this(即可以使用其他实例成员)。
  • 可用于设置基类成员。

缺点:

  • 不能用于初始化非late final也不是不可为空的成员。
  • 如果类有多个构造函数,则需要重复初始化或需要重构初始化代码(例如但不限于重定向到公共构造函数)。
  • 成员已初始化after调用基类构造函数。
  • 如果构造函数有一个隐藏成员变量的参数,则很容易意外引用该参数而不是成员。 (看https://github.com/dart-lang/linter/issues/2552 https://github.com/dart-lang/linter/issues/2552了解详情。)

我可能忘记了一些要点,但我认为这应该涵盖主要要点。

首先发生直接内联初始化,然后是初始化列表,然后是构造函数体。另请参阅在参数列表和初始化列表中分配值之间的区别 https://stackoverflow.com/a/63319094/,这解释了为什么this仅对对象初始化的后期阶段有效。

举个例子,成员的初始化位置很重要:

class Base {
  Base() {
    doSomething();
  }

  void doSomething() {}
}

class DerivedEarly extends Base {
  int? x;

  DerivedEarly() : x = 42;

  @override
  void doSomething() => print(x);
}

class DerivedLate extends Base {
  int? x;

  DerivedLate() {
    x = 42;
  }

  @override
  void doSomething() => print(x);
}

void main() {
  DerivedEarly(); // Prints: 42
  DerivedLate(); // Prints: null
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Dart 中成员变量的初始化方式有什么不同吗? 的相关文章

随机推荐