匹配(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