34、match(模式匹配)

match(模式匹配)

 

枚举类型比较常用的应用场景是用match语句来进行模式匹配。

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语句。在上面的代码中,如果statusDone这个枚举变体,就执行第一个代码块,如果statusInProgress枚举变体或ToDo枚举变体,则执行第二个代码块。

 

详尽性

 

这里有一个关键的细节:match是详尽的。我们必须处理所有的枚举变体。

如果我们忘记了处理某个枚举变体,那么Rust会在拒绝编译代码。

 

比如,如果我们忘记处理ToDo变体:

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

 

全部匹配

 

如果我们不关心其中的一个或多个变体,可以使用_模式来实现全部匹配:

match status {
    Status::Done => true,
    _ => false
}

 

_匹配会匹配前面的模式没有匹配到的变体。

通过使用这种通配模式,我们将无法享受到编译器驱动重构的优势。如果我们添加了一个新的枚举变体,编译器将不会提示我们未处理该变体。

 

为了确保很高的正确性,安全性,可以尽量避免使用_

 

练习

 

实现一个n_sides方法,可以根据Shape枚举变体的边数输出对应的边

 

题目:

pub enum Shape {
    Circle,
    Square,
    Rectangle,
    Triangle,
    Pentagon,
}

impl Shape {
    // TODO: Implement the `n_sides` method using a `match`.
    pub fn n_sides(&self) -> u8 {
        /* TODO */    }
}

 

答案:

use crate::Shape::{Circle, Square};

pub enum Shape {
    Circle,
    Square,
    Rectangle,
    Triangle,
    Pentagon,
}

impl Shape {
    // TODO: Implement the `n_sides` method using a `match`.
    pub fn n_sides(&self) -> u8 {
        match &self {
            Shape::Circle => 0,
            Shape::Square => 4,
            Shape::Rectangle => 4,
            Shape::Triangle => 3,
            Shape::Pentagon => 5,
        }
    }
}

 

这一节的学习就先到这了。

阅读剩余
THE END