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

枚举 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,284评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,115评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,614评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,671评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,699评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,562评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,309评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,223评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,668评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,859评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,981评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,705评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,310评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,904评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,023评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,146评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,933评论 2 355

推荐阅读更多精彩内容