可空与非空
本课属于 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 提供的运算符,以便安全地处理可空值。
挑战
简单让我们构建一个电影待看列表系统,用可空类型和不可空类型来展示必填信息与可选信息之间的区别。
你将创建两个文件来组织代码:
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()
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器