late 关键字与空安全
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 26 课,共 110 课。
有时你需要一个不可空变量,但无法立即为它赋值。late 关键字告诉 Dart:“我保证在使用它之前初始化它。”
late String description;
void setup() {
description = 'Initialized later';
}
void main() {
setup();
print(description); // 可以正常运行:使用前已初始化
}如果没有 late,Dart 会提示 description 尚未初始化。使用 late 后,你需要负责确保在访问它之前为它赋值。如果你在初始化之前尝试读取它,就会遇到运行时错误。
一个常见的用例是延迟执行开销较大的计算,直到真正需要时再执行:
class DataProcessor {
late List<int> data = _loadData();
List<int> _loadData() {
print('Loading data...');
return [1, 2, 3, 4, 5];
}
}
DataProcessor processor = DataProcessor();
// 还没有打印 'Loading data...'
print(processor.data); // 现在会加载数据并打印出来只有在首次访问 data 时,才会运行 _loadData() 方法,而不是在创建对象时运行。如果这个值可能永远用不到,这种延迟初始化方式可以提高性能。
当你确定某个变量会在使用前初始化,但无法在声明时完成初始化,就使用 late。这是对编译器的承诺。违背这个承诺,程序就会崩溃。
挑战
简单让我们构建一个配置管理器,展示使用 late 变量延迟初始化的优势。你将创建一个系统,只有在实际需要配置时才执行开销较大的设置操作。
你将把代码分成两个文件:
config_manager.dart:定义一个用于处理应用设置的ConfigManager类。这个类应包含:- 通过构造函数传入的
String appName - 一个稍后通过设置方法初始化的
late String databaseUrl - 一个采用惰性初始化的
late int maxConnections,首次访问时打印Calculating max connections...,并返回100 - 一个用于初始化
databaseUrl的setupDatabase(String url)方法 - 一个用于打印当前配置的
displayConfig()方法
- 通过构造函数传入的
main.dart:导入配置管理器,并演示late变量的工作方式:- 创建一个应用名称为
'MyApp'的ConfigManager - 打印
Config created - 调用
setupDatabase,并传入 URL'localhost:5432/mydb' - 打印
Accessing max connections... - 打印
maxConnections的值 - 打印
Accessing max connections again... - 再次打印
maxConnections的值(注意,计算提示不会重复出现) - 调用
displayConfig()
- 创建一个应用名称为
displayConfig() 方法应按以下格式打印:
--- Configuration ---
App: [appName]
Database: [databaseUrl]
Max Connections: [maxConnections]注意,惰性计算的 maxConnections 只会运行一次,也就是你首次访问它时。这就是使用带初始化器的 late 的好处!
预期输出:
Config created
Accessing max connections...
Calculating max connections...
100
Accessing max connections again...
100
--- Configuration ---
App: MyApp
Database: localhost:5432/mydb
Max Connections: 100亲手试试
import 'config_manager.dart';
void main() {
// TODO: 创建一个应用名称为 'MyApp' 的 ConfigManager
// TODO: 打印 'Config created'
// TODO: 使用 URL 'localhost:5432/mydb' 调用 setupDatabase
// TODO: 打印 'Accessing max connections...'
// TODO: 打印 maxConnections 的值
// TODO: 打印 'Accessing max connections again...'
// TODO: 再次打印 maxConnections 的值
// (注意,计算时的消息不会重复出现)
// TODO: 调用 displayConfig()
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器