Skip to main content

Enum 和模式匹配

enum 的简单用法是:

enum IpAddrKind {
V4,
V6,
}

let four = IpAddrKind::V4;
let six = IpAddrKind::V6;

Enum 也可以有关联值:

enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}

let home = IpAddr::V4(127, 0, 0, 1);;

let loopback = IpAddr::V6(String::from("::1"));

当 enum 的关联值是 Copy 类型时, 对应的 enum 对象是在栈上分配的, 否则是在堆上.

再看一个复杂的例子, 这个例子中 enum 的关联值有匿名 struct:

struct SomeType;

enum Message {
Quit,
Move { x: i32, y: i32 }, // 匿名结构体
Write(String), // 普通 struct
Read(SomeType), // Unit like struct
ChangeColor(i32, i32, i32),
}

和 struct 类似, enum 也可以定义方法:

impl Message {
fn call(&self) {
// method body would be defined here
}
}

Rust 中的 Option enum

Rust 中没有空指针的概念, 而是通过 Option 中的 None 值表示空:

enum Option<T> {
None,
Some(T),
}

let some_number = Some(5);
let some_char = Some('e');

let absent_number: Option<i32> = None;

这样可以完全避免出现空指针误用的情况.

使用 match 进行模式匹配

语法上比较简单:

enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}

fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}

如果要在匹配过程中抽取关联值, 则可以:

fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
// 关联值可以直接拿到
Coin::Quarter(state) => {
println!("State quarter from {:?}!", state);
25
}
}
}

// 对 Option 的匹配:

fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
}
}

还可以通过 _ 忽略其它的分支(arm):

let dice_roll = 9;

match dice_roll {
3 => add_fancy_hat(),
7 => remove_fancy_hat(),
// 其它情况的处理, 类似 switch 的 default 块
_ => reroll(),
}

使用 if let 进行精确匹配

语法和 swift 的类似, 只是需要将 enum 值放前面:

let config_max = Some(3u8);
if let Some(max) = config_max {
println!("The maximum is configured to be {}", max);
} else {
println!("no value here");
}