枚举和模式匹配
https://rustwiki.org/zh-CN/book/ch06-00-enums.html
枚举基础
枚举和结构类似,都有自己的变量和方法,不过枚举更倾向于列举出所有的可能性。
枚举可以作为数据类型
自己定义枚举 IP = {v4, v6}
fn main() {
// 定义枚举
#[derive(PartialEq)] // to use "=="
enum IpAddrKind {
V4,
V6,
}
// 访问枚举
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
// 作为函数参数类型
fn route(ip_type: IpAddrKind) {
if ip_type == IpAddrKind::V4 {
println!("Type of route is V4");
} else {
println!("Type of route is V6");
}
}
route(four); // Type of route is V4
route(six); // Type of route is V6
}
枚举可以包含数据,关联方法(有点像结构体了)
fn main() {
// 枚举可以包含数据
#[derive(PartialEq)]
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
impl IpAddr {
fn test(&self) {
println!("我也不知道干点啥\n");
}
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
home.test();
}更好的方案,enum 里边套结构体
这个是rust 标准库里边对 IP 类型枚举的实现方案
#![allow(unused)]
fn main() {
struct Ipv4Addr {
// --snip--
}
struct Ipv6Addr {
// --snip--
}
enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr),
}
}
Option 枚举和其相对于空值的优势
空值容易引发错误的原因是,人们按照非空的方式去调用空。
rust如何解决的:空与非空也是一种枚举,他就是 Option!
// rust 中对 Option 的定义
enum Option<T> {
Some(T),
None,
}如果我们写了下面的函数,并尝试运行
let x: i8 = 5;
let y: Option<i8> = Some(5);
let sum = x + y;这不会通过!因为 rust 不会把i8和 Option<i8>加在一起。我们需要手动把Option<i8>转换成i8,这样就可以保证,所有可以编译通过的代码不会把空加进去了。
上边我还在想,定义了枚举类型,怎么进行类型判断,这不就来了
Match Demo( 匹配纯类型的 enum)
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 main() {
println!("{}", value_in_cents(Coin::Penny));
println!("{}", value_in_cents(Coin::Nickel));
println!("{}", value_in_cents(Coin::Dime));
}Match Demo( 匹配有数据的 enum)
#[derive(Debug)]
enum UsState {
Alabama,
Alaska,
// ....
}
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
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
}
}
}
fn main() {
println!("{}", value_in_cents(Coin::Penny));
println!("{}", value_in_cents(Coin::Nickel));
println!("{}", value_in_cents(Coin::Quarter(UsState::Alabama)));
}
匹配 Option<T>
之前说的 Option 还没说处理方案:比如可能是空的数要加一,方法为,空还是空,数+1
fn main() {
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
None => None,
Some(i) => Some(i + 1),
}
}
// 这个会报错,因为没写 None,对 enum 的匹配需要是穷尽的
// fn plus_one(x: Option<i32>) -> Option<i32> {
// match x {
// Some(i) => Some(i + 1),
// }
// }
let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
}通配模式和 _ 占位符
如果不是对 enum 的匹配,比如输入一个数,根据大小进行后续判断。就要用到“other”。
fn main() {
let dice_roll = 9;
match dice_roll {
3 => add_fancy_hat(),
7 => remove_fancy_hat(),
other => move_player(other),
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn move_player(num_spaces: u8) {}
}如果不需要获取 other 的值,也可以用通配符"_"
fn main() {
let dice_roll = 9;
match dice_roll {
3 => add_fancy_hat(),
7 => remove_fancy_hat(),
_ => reroll(),
// _ => (), // 可以用空的(),代表“无事发生”
}
fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn reroll() {}
}if let 可以简化代码。可以认为 if let 是 match 的一个语法糖,它当值匹配某一模式时执行代码而忽略所有其他值。
最后更新于
这有帮助吗?