【问题标题】:Can late and final be used together?late 和 final 可以一起用吗?
【发布时间】:2021-01-10 06:22:38
【问题描述】:
我现在正在尝试 NNBD,我想知道您是否可以同时使用新关键字 late 和 final。
据我了解,late 属性可以在任何地方设置。您基本上是在告诉分析器,它在使用时不会为空。
我认为这在某些情况下有点危险。
所以我想知道您是否可以在 NNBD 中添加 late final,这将告诉分析器该属性必须在类构造函数中初始化。
有一个类似的问题,但我想当时没有空安全:
Dart. Late initialize final variables
【问题讨论】:
标签:
dart
dart-null-safety
【解决方案1】:
是的!
可以看到初始化AnimationController时常用的这种模式。
class _MyState extends State<MyPage> with SingleTickerProviderStateMixin {
late final AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this);
}
}
你可以用它来进行延迟初始化,比如:
class Foo {
late final int i = calculate; // Initialized only when used.
int get calculate => ...;
}
【解决方案2】:
您可以声明一个late final 变量。
如果你声明它用一个初始化器,late final foo = computeSomething();,那么它就是一个惰性最终变量。您不能分配给变量,但它的值仅在第一次读取变量时计算。 (根据我的经验,对于 local 变量来说,这绝不是正确的选择,即使语言允许这样做。如果您关心局部变量的延迟初始化,您几乎总是想知道 它是否已初始化,并且惰性变量不会为您提供该信息。代码乱序执行也令人困惑,并且不允许您在初始化程序中使用 await表达式)。
如果你声明一个late final 变量没有初始化器,你可以写入变量一次。因为变量是late,所以编译器不会在编译时抱怨分配,除非绝对确定您已经分配了变量,并且只有当它是一个局部变量时(因为这是编译器尝试的唯一变量跟踪分配)。
如果没有初始化器的late final 变量是类的实例成员,这意味着类接口有一个setter。您需要非常非常小心地在类的公共 API 中公开 late final 变量。 (阅读:不要那样做!)
最好在内部使用后期变量并保护对字段的访问,这样您就可以确保没有人将变量分配两次。后期最终变量的目标是如果它被分配了两次就不会抛出。它不应该被分配两次。它允许由于某种原因编译器无法理解的知道的代码,该变量只分配一次。因此,只允许对知道该原因并保持不变性的代码访问后期最终变量。