枚举和模式匹配(6)

枚举和模式匹配

    • 1.枚举和模式匹配
      • 1.1枚举的定义
        • 1.枚举值
          • 1.1枚举成员中内嵌多种多样的类型
          • 1.2枚举和结构体类似
        • 2.Option枚举和其相对于空值的优势
      • 1.2match控制流结构
        • 1.枚举和以枚举成员作为模式的match表达式
        • 2.绑定值得模式
        • 3.匹配Option
        • 4.匹配是穷尽的
        • 5.通配模式和 _ 占位符
      • 1.3if let简洁控制流

1.枚举和模式匹配

  • 枚举允许通过列举可能的成员来定义一个类型

1.1枚举的定义

  • 以现在广泛使用的主要IP标准: IPV4 和 IPV6
enum IpAddrKind{
	V4,
	V6,
}

  • IpAddrKind就是一个可以在代码中使用的自定义数据类型
1.枚举值
#[derive(Debug)]
enum IpAddrKind {
    V4,
    V6,
}
#[derive(Debug)]
struct IpAddr {
    kind: IpAddrKind,
    address: String,
}

fn main() {
    let local = IpAddr {
        kind: IpAddrKind::V4,
        address: String::from("127.0.0.1"),
    };
    let loopback = IpAddr {
        kind: IpAddrKind::V6,
        address: String::from("::1"),
    };
    println!("The local address is {}", local.address);
    dbg!(&loopback);
}


  • 将数据附加到枚举的每个成员,就不需要单独的结构体
  • 枚举代替结构体,优势是每个成员可以处理不同类型和数量的数据
enum IpAddr{
	V4(u8,u8,u8,u8);
	V6(String),
}
let local = IpAddr::V4(127.0.0.1);
let loopback = IpAddr::V6(String::from("::1"));
1.1枚举成员中内嵌多种多样的类型
  • Quit没有关联任何数据
  • Move类似结构体包含命名字段
  • Write包含单独一个String
  • ChangeColor 包含三个 i32
enum Message{
	Quit,
	Move { x: i32,y: i32},
	Write(String),
	ChangeColor(i32,i32,i32),
}

1.2枚举和结构体类似
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

// 效果同上
// struct QuitMessage;
// struct MoveMessage {
//     x: i32,
//     y: i32,
// }
// struct WriteMessage(String);
// struct ChangeColor(i32, i32, i32);

impl Message {
    fn call(&self) {}
}

fn main() {
    let message = Message::Write(String::from("自强不息"));
    message.call();
}
2.Option枚举和其相对于空值的优势
  • 在rust语言中,没有空值,不过有一种可以编译存在或不存在概念的枚举,这个枚举是Option
  • 定义与标准库中
enum Option<T>{
	None,
	Some<T>,
}

1.2match控制流结构

1.枚举和以枚举成员作为模式的match表达式
  • match是一种极其强大的控制流运算符
enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}
fn main() {
    let coin = Coin::Penny;
    value_in_cents(coin);
}
fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => {
            println!("Lucky penny"); // Lucky penny
            1
        }
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

2.绑定值得模式
  • 匹配分支的另一个有用的功能是可以绑定匹配的模式的部分值
#[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() {
    value_in_cents(Coin::Quarter(usState::Alaska));
}

3.匹配Option
  • 编写一个函数,获取一个Option;如果其中含有一个值,将其加1,如果其中没有值,函数应该返回None值
fn main() {
    let five = Some(5);
    let six = plus_one(five);
    let none = plus_one(None);
}
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

4.匹配是穷尽的
  • match这些分支必须覆盖所有的可能性
use rand::Rng;

fn main() {
    let num = rand::thread_rng().gen_range(1..=10);
    games_rules(num)
}
fn games_rules(num: i32) {
// error,对可能出现的结果没实现全覆盖
    match num {
        3 => add_fancy_hat(),
        // 7 => remove_fancy_hat(),
        // _ => move_player(),
    }
}

fn add_fancy_hat() {
    println!("获得一顶帽子");
}
fn remove_fancy_hat() {
    println!("失去一顶帽子")
}
fn move_player() {
    println!("移动一步");
}

5.通配模式和 _ 占位符
  • _ 代表其他可能性
use rand::Rng;

fn main() {
    let num = rand::thread_rng().gen_range(1..=10);
    games_rules(num)
}
fn games_rules(num: i32) {
    match num {
        3 => add_fancy_hat(),
        7 => remove_fancy_hat(),
        _ => move_player(),
    }
}

fn add_fancy_hat() {
    println!("获得一顶帽子");
}
fn remove_fancy_hat() {
    println!("失去一顶帽子")
}
fn move_player() {
    println!("移动一步");
}

1.3if let简洁控制流

  • if let可以简单的看作为match的一个语法糖,它当值匹配某一模式时执行代码而忽略所有其他值
  • if let中包含一个else
let mut count = 0;
match Coin {
	Coin::Quarter(state) => println!("State quarter from {:?}!",state),
	_ => count += 1,
}

或者可以使用这样的if let 和 else 表达式

let mut count = 0;
if let Coin::Quarter(state) = coin {
	println!("State quarter from {:?}!",state);
} else {
	count += 1;
}

你可能感兴趣的:(Rust,rust)