Rust学习笔记(6)

  1. 定义枚举类型
  2. match控制流结构
  3. 用if let实现精简控制流

定义枚举类型

枚举类型基本定义方式:

enum IpAddrKind {
    V4,
    V6,
}
fn main() {
    let four = IpAddrKind::V4;
    let six = IpAddrKind::V6;
}

来点具体的例子

    enum IpAddrKind {
        V4,
        V6,
    }

    struct IpAddr {
        kind: IpAddrKind,
        address: String,
    }

    let home = IpAddr {
        kind: IpAddrKind::V4,
        address: String::from("127.0.0.1"),
    };

    let loopback = IpAddr {
        kind: IpAddrKind::V6,
        address: String::from("::1"),
    };

上面这个写法,在一个结构体里面,混合了一个枚举类型和一个String类型。不过还有更简单的表达方式:

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

    let home = IpAddr::V4(String::from("127.0.0.1"));

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

这个写法,其实就等价于定义了V4和V6两个关联方法,只是没有写实现的地方。

还有泛型的写法:

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

这个用法跟java中的泛型一样,根据实际赋值时候的类型,确定具体类型:

    let some_number = Some(5);
    let some_string = Some("a string");

    let absent_number: Option<i32> = Option::<i32>::None;

match控制流结构

枚举类型用match来进行控制是最合适的,和其他语言一样,就类似用switch-case配合枚举类型一样,看下面的例子:

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

fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => {
            println!("Lucky penny!");
            1
        }
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

同样的,match也可以处理带有值的枚举:

#[derive(Debug)] 
enum UsState {
    Alabama,
    Alaska,
    // --snip--
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}
fn main() {
    let value = value_in_cents(Coin::Quarter(UsState::Alabama));

    println!("{}", value)
}

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
        }
    }
}

带有泛型的枚举也可以用match匹配:

#[derive(Debug)]
enum Option<T> {
    None,
    Some(T),
}
fn main() {

    let five = Option::<i32>::Some(5);
    println!("{:?}", five);

    let six = plus_one(five);
    let none = plus_one(Option::<i32>::None);

    println!("{:?}, {:?}", six, none)
}

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

注意了,match处理的那个None,虽然直接就返回了None,但是也不能缺少。Rust编译时会知道match在匹配枚举类型时缺少了分支没有,一旦缺少,就会提示报错。那么match中有没有像java中的switch-case里面的default来处理其他分支呢?看例子:

    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分支并不需要参数传入,那可以用_来替代other:

    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() {}

如果other分支不需要做任何处理,可以写成这样:

    let dice_roll = 9;
    match dice_roll {
        3 => add_fancy_hat(),
        7 => remove_fancy_hat(),
        _ => (),
    }

    fn add_fancy_hat() {}
    fn remove_fancy_hat() {}

if let实现精简控制流

if let语法比较特别,先看原始的例子:

    let config_max = Some(3u8);
    match config_max {
        Some(max) => println!("The maximum is configured to be {}", max),
        _ => (),
    }

Some就是之前例子里面的枚举类型之一。

我们可以用if let进行简写:

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

let后面跟的就是类似match中跟的匹配形式(pattern),config_max就是用于判断是否符合形式的输入。

再看一个带有else的例子,原始match格式如下:

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

改写成if let形式:

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

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 jimmyseraph@testops.vip

×

喜欢就点赞,疼爱就打赏