延迟初始化
late 关键字的本意是延迟变量的初始化。
// ex431.dart
// int x;
// Error:
// The non-nullable variable 'x' must be initialized.
late int x; // 1
void main() {
x = 1; //2
print(x); // Output: 1
}
- 声明
int类型的变量x并用late关键字修饰它,告诉编译器暂时不对x进行初始化;如果去掉这里的late将引起编译错误The non-nullable variable 'x' must be initialized; - 在使用
x之前对其赋值。
什么时候使用 late
下面按应用场景对late的使用举例说明。
需要使用 non-nullable 变量,但在声明时又无法初始化(比如依赖另一个实例变量/方法 )。
// ex432.dart
class A {
int x;
late int y = x + 1;
A(this.x);
@override
String toString() => '($x, $y)';
}
void main() {
print(A(2)); // Output: (2, 3)
}
此例中变量 y 由变量 x计算而成,用late修饰再方便不过了。
变量的初始化是个费时操作,希望延迟初始化它。
// ex433.dart
import 'dart:math';
class RandAvg {
int n;
late double avg;
RandAvg(this.n);
static final _rand = Random();
void init() {
var s = 0.0;
for (var i = 1; i <= n; i++) {
s += _rand.nextDouble();
}
avg = s / n;
}
}
void main() {
var a = RandAvg(1000_000);
a.init();
print(a.avg);
}
此例中的 avg 是 n 个随机浮点数(取值0-1)的算术平均数,其计算过程由 init() 函数完成。
变量仅在程序的部分地方用到,没用到的地方无需初始化。
// ex434.dart
import 'dart:io';
const kDebug = true;
class Logger {
final String name;
late String _debugInfo;
Logger(this.name);
void ensureDebugInfo() {
if (kDebug) {
_debugInfo =
'OS=${Platform.operatingSystem} CPU cores=${Platform.numberOfProcessors}';
}
}
void log(String message) {
if (kDebug) {
print(_debugInfo);
}
print('${DateTime.now()} $name: $message');
}
}
void main() {
var logger = Logger('main');
logger.ensureDebugInfo();
logger.log('Hi Dart');
}
仅当 kDebug 取值 true 时, Logger类的_debugInfo 才被 log 方法用到, 也才被初始化(由ensureDebugInfo方法完成)。
联合使用 late final
示例 ex433 中的实例变量 avg,在初始化之后便不再改变,这样的变量使用 late final 修饰更为准确,可以有效防止二次计算。
// ex435.dart
class RandAvg {
int n;
late final double avg;
RandAvg(this.n);
}