Menu
CoddyTech

空值感知运算符

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

除了 ?. 和 !,Dart 还提供了其他运算符,让你能更简洁地处理可空值。这些空值感知运算符可以帮助你在处理可能为 null 的值时编写更简洁的代码。

空值合并运算符 ??:如果左侧的值不是 null,就返回左侧的值;否则返回右侧的值:

String? nickname;
String displayName = nickname ?? 'Guest';
print(displayName);  // Guest

nickname = 'Alex';
displayName = nickname ?? 'Guest';
print(displayName);  // Alex

空值感知赋值运算符 ??= 仅当变量当前为 null 时才会赋值:

String? username;
username ??= 'Anonymous';
print(username);  // Anonymous

username ??= 'NewName';
print(username);  // 仍是 Anonymous(之前不是 null)

你可以对嵌套属性连续使用空值感知访问运算符 ?.:

String? city = user?.address?.city;  // 即使 user 或 address 为 null,也不会出错

这些运算符搭配起来很好用。例如,你可以访问一个可空属性,并提供默认值:

String greeting = user?.name ?? 'Stranger';
// 如果 user 为 null,或者 user.name 为 null,就使用 'Stranger'

使用这些运算符可以让代码保持易读,同时确保程序始终具备空安全性。

challenge icon

挑战

简单

让我们构建一个访客登记系统,演示空值感知运算符如何让你在处理可选信息时代码更简洁。

你会把代码整理到两个文件中:

  • guest.dart:定义一个表示活动参与者的 Guest 类。有些访客会提供完整信息,有些只提供基本信息。你的类应包含:
    • 不可为空的 String name:每位访客都必须有名字
    • 可为空的 String? email:不是每个人都会提供电子邮件
    • 可为空的 String? dietaryPreference:有些访客不会说明饮食需求
    • 一个将 name 作为必需参数的构造函数
    • 一个 getDisplayEmail() 方法:如果有电子邮件,就返回电子邮件;否则使用 ?? 运算符返回 'No email provided'
    • 一个 assignDefaultDiet() 方法:仅当 dietaryPreference 当前为 null 时,才使用 ??= 运算符将其设为 'Standard'
    • 一个 getEmailDomain() 方法:使用 ?. 返回电子邮件的长度;如果没有电子邮件,则返回 null
    • 一个 printBadge() 方法:打印访客的徽章信息
  • main.dart:导入你的访客类,并登记三位信息完整程度不同的访客:
    • 创建一位名为 'Alice' 的访客,将她的电子邮件设为 'alice@company.com',饮食偏好设为 'Vegetarian'
    • 创建一位名为 'Bob' 的访客,只将他的电子邮件设为 'bob@email.org'(饮食偏好保持为 null)
    • 创建一位名为 'Charlie' 的访客(电子邮件和饮食偏好都保持为 null)
    • 对这三位访客都调用 assignDefaultDiet()
    • 按顺序处理每位访客:调用 printBadge(),然后使用 getEmailDomain() 打印 Email length: [result]

printBadge() 方法应按以下格式打印:

=== Guest Badge ===
Name: [name]
Email: [getDisplayEmail()]
Diet: [dietaryPreference or "Not specified"]

注意,Alice 的饮食偏好仍然是 'Vegetarian',因为 ??= 只会在值为 null 时赋值;而 Bob 和 Charlie 的饮食偏好会被设为默认值 'Standard'。

预期输出:

=== Guest Badge ===
Name: Alice
Email: alice@company.com
Diet: Vegetarian
Email length: 17
=== Guest Badge ===
Name: Bob
Email: bob@email.org
Diet: Standard
Email length: 13
=== Guest Badge ===
Name: Charlie
Email: No email provided
Diet: Standard
Email length: null

亲手试试

import 'guest.dart';

void main() {
  // TODO:创建一位名叫 'Alice' 的宾客
  // 将她的邮箱设置为 'alice@company.com'
  // 将她的饮食偏好设置为 'Vegetarian'

  // TODO:创建一位名叫 'Bob' 的宾客
  // 只将他的邮箱设置为 'bob@email.org'
  // 将饮食偏好保留为 null

  // TODO:创建一位名叫 'Charlie' 的宾客
  // 将邮箱和饮食偏好都保留为 null

  // TODO:对三位宾客都调用 assignDefaultDiet()

  // TODO:依次对每位宾客(Alice、Bob、Charlie)执行以下操作:
  // - 调用 printBadge()
  // - 使用 getEmailDomain() 打印 'Email length: [result]'
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Dart 在线编译器