Skip to content

1. 枚举

1. 什么是枚举?

枚举是一种数据类型,其能聚合不同成员,你可以通过枚举去匹配成员生成对应成员数据类型的变量。

2. 定义枚举

对于已知所有可能的抽象对象,如Ip地址,通过创建汇枚举以汇聚其所有可能情况。

rust
enum IP{
  V4,
  V6
}
//枚举实例
let A = IP::V4;

//虽然能创建枚举实例,但却没有实际数据类型,可配合结构体实现类型+值
struct IpInfo{
  ip_kind:IP::V4,
  ip_address:String
}

//可以创建带有具体值和种类的IP实例了
let personal = IpInfo{
  ip_kind:IP::V4,
  ip_address:String::from("192.168.11.35")
}

如何在定义枚举时直接关联成员的数据类型?枚举允许直接指定其成员的数据类型,可以将任意类型的数据放入枚举成员中,甚至包括另一个枚举类型。

rust
#![allow(unused)]
fn main() {
  enum Message {
      Quit,
      Move { x: i32, y: i32 },
      Write(String),
      ChangeColor(i32, i32, i32),
  }
  
  //对于上面的IP实例可以作如下修改
  enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
	}

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

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

}

注意:

枚举成员不可以和相同基本数据类型数据进行计算。

rust
enum Matrix{
	x(u32)
}

fn main(){
  let A = 8;
  let B = Matrix::x(10);
  let C = A * B ;//这里A和B不能进行运算
}

3. Option 枚举

Option枚举是标准库定义的枚举,标识一个变量要么有具体值要么什么也没有。其在标准库的定义如下:

rust
#![allow(unused)]
fn main() {
  enum <T> {
      Some(T),
      None,
  }
}

实际使用无需写 ::Some(xxx),只需要Some(T)即可。在对 <T> 进行 T 的运算之前必须将其转换为 T

2. match

match是一个强大的控制流运算符,使用它将一个值与一系列模式去匹配,并根据相匹配的模式执行相应代码。模式可由字面量、变量、通配符和许多其他内容构成。

Rust 中的match是穷举式的exhaustive):必须穷举到最后的可能性来使代码有效。

1. 模式匹配Option<T>

当match到对应类型的数据时,为了满足穷举机制,None的情况要始终被覆盖:

rust
//模拟实现一个匹配Option<i32>的示例
fn plus(x:<i32>) -> <i32>{
  match x {
    None => None,
    Some(i) => Some(i+1)
  }
}

fn main(){
  let n = plus(None);
  let six = plus(Some(5))
}
2. 通配符和_占位符

在实际应用中,如果需要处理某些特定值之外的所有值的情况,可以使用通配符来处理。通配符不是某个具体的符号,而是一个自定义的无实际意义的“形参”。

rust
//模拟在飞行棋游戏中,掷骰子,设定1和6为特殊点数,其他点数则前进对应格数
use rand::Rng;
...
fn toe(x:u32){
  match x {
    1 => punish(),
    6 => rewards(),
    other => move(other)
    //当到其他点数时,要求重投掷
    //_ => roll_again()
  }
}
fn main(){
  let secret_number = rand::thread_rng().gen_range(1..7);
  toe(secret_number)
}

注意:

通配符会获取模式的值、占位符则不会,因此占位符适合在不需要获取到模式值的情况使用。

3. if let简单控制流

if let是对match的一种简化,用于只想处理某一个模式的情况,match需要写通配符或者占位符实现,但依旧要对其余情况做处理,而使用if let则完全不用考虑其他模式。

rust
//比如想匹配一个Option u8类型

//match实现

#![allow(unused)]
fn main() {
  let some_u8_value = Some(0u8);
  match some_u8_value {
      Some(3) => println!("three"),
      _ => (),
  }
}

//if let实现

#![allow(unused)]
fn main() {
  let some_u8_value = Some(0u8);
  if let Some(3) = some_u8_value {
      println!("three");
  }
}

此外,可以在 if let 中包含一个 elseelse 块中的代码与 match 表达式中的占位符 _ 分支块中的代码相同。

rust

#![allow(unused)]
fn main() {
#[derive(Debug)]
  enum UsState {
     Alabama,
     Alaska,
  }

  enum Coin {
     Penny,
     Nickel,
     Dime,
     Quarter(UsState),
  }
  let coin = Coin::Penny;
  let mut count = 0;
  //match实现穷尽模式
  match coin {
      Coin::Quarter(state) => println!("State quarter from {:?}!", state),
      _ => count += 1,
  }
  //if let实现
  if let Coin::Quarter(state) = coin {
      println!("State quarter from {:?}!", state);
  } else {
      count += 1;
  }
}