类中的空安全
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 28 课,共 110 课。
设计类时,你需要决定哪些字段是必需的,哪些是可选的。空安全会影响你声明实例变量和编写构造函数的方式。
非空字段必须在构造函数体运行之前完成初始化。你可以通过初始化列表、构造函数参数或默认值来完成:
class User {
String name; // 必须初始化
String? bio; // 可选,可以为 null
int age = 0; // 有默认值
User(this.name); // 通过参数初始化 name
}对于可空字段,你可以不初始化它们,因为它们默认值为 null。这适用于可选数据:
class Product {
String title;
String? description; // 可选的商品描述
double? discount; // 默认没有折扣
Product(this.title);
}
var item = Product('Laptop');
print(item.description); // null
print(item.discount); // null访问可空字段时,请使用你学过的空值感知运算符:
class Order {
String id;
User? customer;
Order(this.id);
String getCustomerName() {
return customer?.name ?? 'Guest';
}
}命名参数中的 required 关键字可确保调用者提供必要的值:
class Account {
String email;
String? phone;
Account({required this.email, this.phone});
}
var acc = Account(email: 'test@mail.com'); // phone 是可选的通过认真选择可空字段和不可空字段,你可以创建清晰表达哪些数据是必需的、哪些是可选的类。
挑战
简单我们来为一家酒店构建一个预订系统,展示如何在空安全中合理搭配必填字段和可选字段来设计类。
你要把代码整理到两个文件中:
reservation.dart:定义一个表示酒店预订的Reservation类。每笔预订都需要一些必要信息,但有些详情是可选项,客人可能会提供,也可能不会提供。你的类应包含:- 一个不可空的
String guestName,每笔预订都必须有客人姓名 - 一个不可空的
int roomNumber,每笔预订都必须分配房间 - 一个不可空的
int nights,默认值为1,最短住宿时间为一晚 - 一个可空的
String? specialRequests,客人可能会有特殊要求 - 一个可空的
DateTime? checkInTime,可能无法确定确切的到达时间 - 一个使用命名参数的构造函数,其中
guestName和roomNumber使用required,而nights为可选参数,并设有默认值 - 一个名为
getRequestsSummary()的方法,如果提供了特殊要求,就返回这些要求;否则使用??运算符返回'No special requests' - 一个名为
getArrivalInfo()的方法,使用?.返回入住时间的字符串表示;如果未设置,则返回null - 一个名为
printConfirmation()的方法,用于显示预订详情
- 一个不可空的
main.dart:导入预订类,并创建预订,展示必填数据和可选数据的不同组合:- 为客人
'Sarah Johnson'创建一笔预订,房间号为101,入住3晚,特殊要求为'Late checkout',入住时间设为DateTime(2024, 6, 15, 14, 30) - 为客人
'Mike Chen'创建一笔预订,房间号为205(使用默认的住宿晚数),只设置特殊要求'Extra pillows' - 为客人
'Emma Davis'创建一笔预订,房间号为310,入住2晚(两个可选字段都保持为 null) - 按顺序处理每笔预订,调用
printConfirmation(),然后使用getArrivalInfo()打印Arrival: [result]
- 为客人
printConfirmation() 方法应按以下格式打印:
=== Reservation Confirmed ===
Guest: [guestName]
Room: [roomNumber]
Nights: [nights]
Requests: [getRequestsSummary()]预期输出:
=== Reservation Confirmed ===
Guest: Sarah Johnson
Room: 101
Nights: 3
Requests: Late checkout
Arrival: 2024-06-15 14:30:00.000
=== Reservation Confirmed ===
Guest: Mike Chen
Room: 205
Nights: 1
Requests: Extra pillows
Arrival: null
=== Reservation Confirmed ===
Guest: Emma Davis
Room: 310
Nights: 2
Requests: No special requests
Arrival: null亲手试试
import 'reservation.dart';
void main() {
// TODO:为 'Sarah Johnson' 创建预订
// 101 号房,住 3 晚,特殊要求:'Late checkout'
// 入住时间:DateTime(2024, 6, 15, 14, 30)
// TODO:为 'Mike Chen' 创建预订
// 205 号房,使用默认入住晚数,特殊要求:'Extra pillows'
// 未指定入住时间
// TODO:为 'Emma Davis' 创建预订
// 310 号房,住 2 晚,无特殊要求,未指定入住时间
// TODO:按顺序对每个预订执行以下操作:
// 1. 调用 printConfirmation()
// 2. 使用 getArrivalInfo() 打印 'Arrival: [result]'
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器