我有这个代码:
void main() {
RethinkDb r = RethinkDb();
Connection connection;
UserService sut;
setUp(() async {
connection = await r.connect(host: "127.0.0.1", port: 28015);
await createDb(r, connection);
sut = UserService(r, connection); // second line
});
test('creates a new user documenet in database', () async {
final user = User(
userName: 'test',
photoUrl: 'url',
active: true,
lastSeen: DateTime.now(),
);
final userWithId = await sut.connect(user); // first line
expect(userWithId.id, isNotEmpty);
});
}
我在“第一行”有一个错误,说
sut
变量必须被初始化,但是当你看“第二行”时,你可以看到sut
确实被初始化了,并且setUp()
函数在 test()
之前被调用。
可以初始化 如果你打算稍后分配它,你的变量就像这样
UserService? sut
或
late UserService sut
在某些情况下,即使对于没有初始值的不可空变量,您也不需要显式使用
late
。例如:
void main() {
int x;
x = 42;
print(x);
}
或:
import 'dart:math';
void main() {
int x;
if (Random().nextBool()) {
x = 1;
} else {
x = 0;
}
print(x);
}
在那些情况下,通过控制流分析,编译器可以保证所有代码路径导致
x
在使用之前被初始化。
但是当你看“第二行”时,你可以看到
确实被初始化了,并且在sut
之前调用了setUp()
函数。test()
问题在于
setUp()
的语义在 test()
之前被调用(或者更准确地说,setUp
的 callback 在 test
的 callback 之前执行)是测试描述的行为框架,而不是语言。编译器确定 setUp
回调是 guaranteed 在 test
回调之前执行是非常重要的。确定这将涉及对这些函数(以及它们调用的任何函数等)的实现执行流分析,这可能非常昂贵。
这就是
late
关键字存在的全部原因:告诉编译器 you 比它知道的更多。使用 late
意味着您亲自保证变量在使用前会被初始化。