美文网首页Rust 学习笔记
Rust基础学习-11-枚举的使用

Rust基础学习-11-枚举的使用

作者: 一个游戏开发者 | 来源:发表于2019-10-10 13:08 被阅读0次

    枚举 enum,用于从众多选项中选择一个。

    定义枚举

    #[derive(Debug)]
    enum Week {
        Monday,
        Tuesday,
        Wednesday,
        Thursday,
        Friday,
        Saturday,
        Sunday,
    }
    
    fn main() {
        let today = Week::Saturday;  // 使用枚举
        let tomorrow = Week::Sunday;
    
        println!("{:?}", today);
    }
    

    这是我们在很多面向对象语言中常见的定义枚举的方式

    以往对枚举的认识,就是枚举限定了几个固定的选项,我们只能使用众多选项中的一个,或者说,只是使用了某一个元素的名字,例如上面Week枚举中的Monday,至于Monday是什么,无所谓,Monday = 1也好,Monday = 10也好,我们并不关心。但是对于Rust,我们对枚举有更进一步的应用。

    用枚举代替结构体

    #[derive(Debug)]
    enum IpAddr {
        V4(u8, u8, u8, u8), // 这个枚举成员是四个u8类型的元祖
        V6(String), // 这个枚举成员是String类型
    }
    
    fn main() {
        // 定义一个枚举变量,并将四个值存放
        let loopbackV4 = IpAddr::V4(127, 0, 0, 1);
      
        // 定义另一个枚举变量,存入一个 String 类型的值
        // "xxx".to_string() 方法和 String::from("xxx") 是一样的效果
        let loopbackV6 = IpAddr::V6("::1".to_string());
    
        println!("{:?}\n{:?}", loopbackV4, loopbackV6);
    }
    

    上面的代码,我们可以给枚举的每一个成员,指定一个数据类型,并且在创建一个枚举变量的时候,将某个值存入枚举。在 struct 中可以存储不同类型的变量,现在,在枚举中也可以。

    再来看一个例子

    // 定义一个操作枚举
    #[derive(Debug)]
    enum Operation {
        Move {x: i32, y:i32},
        Jump(u32),
        Attack(i32),
    }
    
    fn main() {
        // 定义一个移动的操作
        let opt_move = Operation::Move {x: 10, y: 11};
      
        // 定义一个攻击的操作
        let opt_attack = Operation::Attack(100);
      
        // 定义一个跳跃的操作
        let opt_jump = Operation::Jump(3);
    
        DoOperation(opt_move);
        DoOperation(opt_attack);
        DoOperation(opt_jump);
    }
    
    // 执行操作
    fn DoOperation(opt: Operation) {
        println!("Do operation: {:?}", opt);
    }
    

    上面的代码我们定义了一个 Operation 枚举,里面有移动,攻击和跳跃三种操作方式。在 main 中定义了三个操作的变量,并且将每一次操作的具体值直接附加到了枚举成员上,例如 opt_attack 攻击操作,这次操作的伤害是100。

    Rust 中使用 enum 代替 struct 将获得更简洁的代码。并且,每个枚举成员可以处理不同类型和数量的数据。

    Rust 的 Option 枚举解释

    Rust 中没有 Null 值,无法将一个变量赋值为 Null, 例如 let a = Null;,这样的操作在Rust中不存在。但是Rust中有 Option 枚举,这个枚举,用于表示 存在不存在 的概念。有点抽象,没关系,一步一步来,先看下 Option 源代码的定义

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

    这里的 <T> 是指可以代表任何数据类型的,这是范型相关的东西,后面会学习。可以将 Option 枚举想象成可以装不同类型东西的小盒子,例如我们定义了一个装玩具汽车的小盒子,这个小盒子里只能装玩具汽车。任何时候,只要这个盒子存在,那么里面就会有两种状态,要么有玩具汽车,要么没有玩具汽车。在有些面向对象的语言中,如果访问一个玩具汽车,而恰好当时那里没有玩具汽车,那么就会造成空引用,如果没有手动处理空引用的情况,则程序就会出现Bug。而Rust则避免了 空引用 的情况。

    看下面的代码

    fn main(){
      // 使用 Option 将一个 String 类型的值包起来
      let name: Option<String> = Some("Fred".to_string());
    }
    

    Option 用于某些地方可能存在有值或没值的情况。Option 及成员已经被自动包含,所以我们不需要 Option::Some(xxx) 这样来使用。

    match 匹配

    对于 enum 类型的值,我们不能直接比较,看下面的代码,是无法编译通过的。

     let name: Option<String> = Option::Some("Jack".to_string());
    println!(name == "Jack".to_string());
    

    上面代码中 name == "Jack".to_string() 编译出错,因为 == 两边的数据类型不一样。这里,我们就可以用到 match

    看下面的代码

    #[derive(Debug)]
    enum Operation {
        Move {x: i32, y:i32},
        Jump(u32),
        Attack(i32),
        Talk(String),
    }
    
    fn main() {
        let opt_talk = Operation::Talk("Hello".to_string());
        let opt_move = Operation::Move { x: 10, y: 20 };
    
        match opt_move {
            Operation::Talk(ref value) => { // 这里加了 ref 是为了避免所有权转移
                println!("Talk: {:?}", value);
            },
            Operation::Move {x,y} => {
                println!("Move, x: {}, y: {}", x, y);
            }
            _ => {
                // nothing
            }
        }
    }
    

    上面的代码中,match Operation 枚举时,并没有匹配所有的情况,所以最后需要 _ => ,相当于某些编译语言中 switch 中的 default,即在上面的情况都不匹配的情况下,执行的操作。

    if let 使用

    直接看代码,简化上面 match 的操作

    if let Operation::Move{x, y} = opt_move {
        println!("Move, x: {}, y: {}", x, y);
    } else {
        println!("nothing");
    }
    

    这样就可以不用 match 直接匹配枚举中的某一个成员类型。

    感觉这篇博客有些地方写的可能不是很清楚,说明我对这块知识的理解程度还不够。下面是一些讲解 Rust 枚举的链接

    https://rustwiki.org/zh-CN/rust-by-example/custom_types/enum.html

    https://www.twle.cn/c/yufei/rust/rust-basic-enums.html

    http://www.ameyalokare.com/rust/2017/10/23/rust-options.html

    相关文章

      网友评论

        本文标题:Rust基础学习-11-枚举的使用

        本文链接:https://www.haomeiwen.com/subject/xuwopctx.html