延迟初始化
late
关键字的本意是延迟变量的初始化。
// ch0403_1.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 变量,但在声明时又无法初始化(比如依赖另一个实例变量/方法 )。
// ch0403_2.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
修饰再方便不过了。
变量的初始化是个费时操作,希望延迟初始化它。
// ch0403_3.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()
函数完成。
变量仅在程序的部分地方用到,没用到的地方无需初始化。
// ch0403_4.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
示例 ch0403_3.dart
中的实例变量 avg
,在初始化之后便不再改变,这样的变量使用 late final
修饰更为准确,可以有效防止二次计算。
// ch0403_5.dart
class RandAvg {
int n;
late final double avg;
RandAvg(this.n);
}