匹配(match)
你可能在想,枚举(enum)究竟能做些什么?最常见的操作就是**匹配(match)**它。
#![allow(unused)] fn main() { enum Status { ToDo, InProgress, Done } impl Status { fn is_done(&self) -> bool { match self { Status::Done => true, // The `|` operator lets you match multiple patterns. // It reads as "either `Status::ToDo` or `Status::InProgress`". Status::InProgress | Status::ToDo => false } } } }
match
语句让你能把Rust值与一系列模式进行比较。你可以把它想象成类型级别的if
。如果status
是已完成
变体,执行第一块代码;如果是进行中
或待办
变体,则执行第二块代码。
完备性
这里的关键点在于match
是完备的。你必须处理所有枚举变体。如果你遗漏了某个变体,Rust会在编译时阻止你并报错。
例如,如果我们忘记处理待办
变体:
#![allow(unused)] fn main() { match self { Status::Done => true, Status::InProgress => false, } }
编译器会报错:
error[E0004]: non-exhaustive patterns: `ToDo` not covered
--> src/main.rs:5:9
|
5 | match status {
| ^^^^^^^^^^^^ pattern `ToDo` not covered
这是一个大优点!代码库随着时间发展,你可能后续会添加新状态,比如Blocked
。Rust编译器会对每个缺失新变体逻辑的match
语句发出错误。这就是为什么Rust开发者经常夸赞“编译器驱动重构”——编译器告诉你接下来要做什么,你只需修复它报告的问题即可。
通配符
如果你不关心一个或多个变体,可以使用_
模式作为通配符:
#![allow(unused)] fn main() { match status { Status::Done => true, _ => false } }
_
模式匹配所有之前模式未匹配到的情况。
参考资料
- 本节练习位于
exercises/05_ticket_v2/02_match