Menu
CoddyTech

可空与非空

本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 24 课,共 110 课。

现在你已经了解了空值安全为什么很重要,接下来看看如何声明可以为 null 的变量。在 Dart 中,在类型名称后添加 ?,就可以让类型允许为空。

String name = 'Alice';   // 不可为 null,必须始终有值
String? nickname;        // 可以为 null,也可以是 String

print(name);      // Alice
print(nickname);  // null

关键区别在于,非空类型保证值一定存在,而可空类型明确允许值不存在。这一区别适用于所有类型:

int count = 10;       // 必须有值
int? optionalCount;   // 可以为 null

List<String> items = [];      // 必须是列表(可以为空)
List<String>? maybeItems;     // 可以为 null(即没有列表)

请注意,空列表 [] 和 null 不同。空列表存在,但不包含任何内容;null 表示列表根本不存在。

编译器会严格执行这些规则。你不能将 null 赋值给不可空变量,也不能在未先检查是否为 null 的情况下,在需要不可空变量的地方使用可空变量:

String? maybeName = 'Bob';
// String definite = maybeName;  // 错误!不能将可空值赋给不可空变量

在下一课中,你将学习 Dart 提供的运算符,以便安全地处理可空值。

challenge icon

挑战

简单

让我们构建一个电影待看列表系统,用可空类型和不可空类型来展示必填信息与可选信息之间的区别。

你将创建两个文件来组织代码:

  • movie.dart:定义一个表示待看列表中电影的 Movie 类。每部电影都必须有片名和上映年份(这两项始终是必填的),但有些其他信息可能并非每部电影都有。你的类应包含:
    • 不可空的 String title,每部电影都必须有片名
    • 不可空的 int year,每部电影都必须有上映年份
    • 可空的 String? director,导演可能未知
    • 可空的 double? rating,并非所有电影都已经有评分
    • 一个将 title 和 year 作为必填参数的构造函数
    • 一个 displayInfo() 方法,用于打印电影信息;导演缺失时显示 Unknown,评分缺失时显示 Not rated
  • main.dart:导入电影类,并创建一个小型待看列表,展示完整和不完整的电影数据:
    • 创建一部片名为 'Inception'、上映年份为 2010 的电影,然后将它的导演设为 'Christopher Nolan',评分设为 8.8
    • 创建一部片名为 'The Matrix'、上映年份为 1999 的电影,然后只设置它的评分为 8.7(导演保持为 null)
    • 创建一部片名为 'Upcoming Film'、上映年份为 2025 的电影(导演和评分都保持为 null)
    • 按上述顺序对每部电影调用 displayInfo()

displayInfo() 方法应按以下确切格式打印:

[title] ([year])
Director: [director or "Unknown"]
Rating: [rating or "Not rated"]

请注意,不可空字段(title 和 year)始终保证有值,而可空字段(director? 和 rating?)可以不设置。这反映了现实场景中的情况:有些数据必不可少,有些则是可选的。

预期输出:

Inception (2010)
Director: Christopher Nolan
Rating: 8.8
The Matrix (1999)
Director: Unknown
Rating: 8.7
Upcoming Film (2025)
Director: Unknown
Rating: Not rated

亲手试试

import 'movie.dart';

void main() {
  // TODO: 创建一部标题为 'Inception'、年份为 2010 的电影
  // 然后将它的 director 设为 'Christopher Nolan',rating 设为 8.8
  
  // TODO: 创建一部标题为 'The Matrix'、年份为 1999 的电影
  // 然后只将它的 rating 设为 8.7(director 保持为 null)
  
  // TODO: 创建一部标题为 'Upcoming Film'、年份为 2025 的电影
  // 让 director 和 rating 都保持为 null
  
  // TODO: 按顺序对每部电影调用 displayInfo()
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Dart 在线编译器