? 和 ! 运算符
本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 25 课,共 110 课。
处理可空类型时,Dart 提供了两个重要的运算符,帮助你安全地访问值。空安全访问运算符 ?. 和 空断言运算符 ! 让你可以控制如何处理可能为 null 的值。
?. 运算符可以安全地访问可空值的属性或方法。如果值为 null,整个表达式会返回 null,而不会导致程序崩溃:
String? name = 'Alice';
print(name?.length); // 5
name = null;
print(name?.length); // null(不会崩溃!)! 运算符告诉 Dart:“我确定这个值不是 null。”它会将可空类型转换为不可空类型,但如果这个值实际上是 null,就会抛出错误:
String? maybeName = 'Bob';
String definite = maybeName!; // 没问题,我们断言它不是 null
print(definite.length); // 3
String? empty = null;
// String crash = empty!; // 运行时错误!值为 null如果你想妥善处理 null 值,请使用 ?.。只有在你绝对确定某个值存在时才使用 !,例如,在用 if 语句检查后,或者你知道逻辑可以保证该值存在。过度使用 ! 会违背空安全的目的,还可能导致运行时崩溃。
挑战
简单让我们构建一个商品库存系统,演示如何使用 ?. 和 ! 运算符安全地处理可空值。
你将创建两个文件来组织代码:
product.dart:定义一个表示库存商品的Product类。有些商品的信息完整,有些商品仍在编目。你的类应包含:- 不可为空的
String name,每件商品都必须有名称 - 不可为空的
double price,每件商品都必须有价格 - 可为空的
String? description,有些商品还没有描述 - 可为空的
String? category,有些商品还没有分类 - 一个构造函数,将
name和price作为必需参数 - 一个
getDescriptionLength()方法,使用?.返回描述的长度;如果没有描述,则返回null - 一个
getCategoryUppercase()方法,使用!返回大写的类别。此方法假定类别已经设置 - 一个
displayProduct()方法,用于打印商品信息;当描述为 null 时显示No description,当类别为 null 时显示Uncategorized
- 不可为空的
main.dart:导入你的商品类,并演示这两个运算符:- 创建一件名为
'Laptop'、价格为999.99的商品,然后将其描述设为'High-performance computing device',类别设为'Electronics' - 创建一件名为
'Mystery Item'、价格为49.99的商品(将描述和类别留为 null) - 对于 Laptop:调用
displayProduct(),使用getDescriptionLength()打印Description length: [length],并使用getCategoryUppercase()打印Category: [uppercase] - 对于 Mystery Item:调用
displayProduct(),并使用getDescriptionLength()打印Description length: [length](这将显示null)
- 创建一件名为
displayProduct() 方法应按以下格式打印:
Product: [name] - $[price]
Description: [description or "No description"]
Category: [category or "Uncategorized"]预期输出:
Product: Laptop - $999.99
Description: High-performance computing device
Category: Electronics
Description length: 32
Category: ELECTRONICS
Product: Mystery Item - $49.99
Description: No description
Category: Uncategorized
Description length: null亲手试试
import 'product.dart';
void main() {
// TODO: 创建一个名为 'Laptop'、价格为 999.99 的产品
// 然后将它的描述设置为 'High-performance computing device'
// 并将它的类别设置为 'Electronics'
// TODO: 创建一个名为 'Mystery Item'、价格为 49.99 的产品
// 让描述和类别保持为 null
// TODO: 对于 Laptop:
// - 调用 displayProduct()
// - 使用 getDescriptionLength() 打印 "Description length: [length]"
// - 使用 getCategoryUppercase() 打印 "Category: [uppercase]"
// TODO: 对于 Mystery Item:
// - 调用 displayProduct()
// - 使用 getDescriptionLength() 打印 "Description length: [length]"
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Dart 在线编译器