Menu
CoddyTech

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。这是对编译器的承诺。违背这个承诺,程序就会崩溃。

challenge icon

挑战

简单

让我们构建一个配置管理器,展示使用 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()
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Dart 在线编译器