一起学Rust-枚举

一、枚举定义及使用

枚举的定义在其他许多的语言中都有实现,举例来说,比如C中的枚举,枚举值在未赋值的情况下默认从0开始递增或从上一个枚举值开始递增,值类型可以是整数或字符类型,实质只能保存整型:

enum {
    A = 'd',  //d 的 ascii码值
    B,        //e 的 ascii码值
    C,        //f 的 ascii码值
    D = 10,
    E,        //11
};

Rust中的枚举与C中的枚举不同,功能非常强大,可以用枚举表达更多的可能性数据。

看一下基本的枚举定义:

//定了一个性别的枚举
enum Gender {
    Male,
    Female,
}

这里面不同的是,Male和Female不是变量,而是枚举值,而不像是C中会访问到相应的数字。

#[derive(Debug)]
enum Gender {
    Male,
    Female,
}

println!("{:?}, {:?}", Gender::Male, Gender::Female);

----- 输出 -----
Male, Female

虽然输出看上去是字符串类型,但实际是枚举Gender类型

//这样是编译不通过的
if Gender::Male == "Male" {...}

枚举值的代数形式是可以与实际的值进行结合的,而且是可以结合不同类型的数据,这使得枚举的能力更强:

enum ErrorLevel {
    Error(String),
    Info(String, i32),
    Warning(String),
}

每一个枚举值可可以放入不同类型的数据,作为枚举的一部分,那么通过下面的例子看一下如何定义带数据的枚举值:

let info = ErrorLevel::Info("info error".to_string(), 3);

match info {
    ErrorLevel::Info(k, v)  => {
        println!("{}, {}", k, v);
    },
    _ => ()
}

上面的例子里面通过模式匹配获取了Info枚举值内的数据,这里需要注意的是上面的例子在match代码块后方就不能再使用info的变量了,这里涉及到Rust中所有权的特性,也是Rust中非常重要的特性,这里暂不过多的探讨。

不过上面的例子仅支持固定类型的值,对于不同级别的错误日志来说,有些时候会需要记录一些不同类型的数据,所以可能需要不同的参数类型(这样说稍微牵强),看下面枚举结合 泛型 的例子:

enum ErrorLevel<T> {
    Error(T),
    Info(T),
    Warning(T),
}
let info = ErrorLevel::Info("abc");  //可以通过自动推断类型
let info = ErrorLevel::<&str>::Info("abc");  //可以指定类型并赋值

三、内置常用枚举

Option<T> 枚举类型,通过IDE可以查看它的完整定义:

#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Option<T> {
    /// No value
    #[stable(feature = "rust1", since = "1.0.0")]
    None,
    /// Some value `T`
    #[stable(feature = "rust1", since = "1.0.0")]
    Some(#[stable(feature = "rust1", since = "1.0.0")] T),
}

简化如下

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

Option<T> 是一个非常重要的枚举类型,在程序中无需引用库,直接可以使用Some(T)和None。另外一个原因是因为Rust中去除了空类型,也就是没有null、nil、none、这种在其他语言中非常常见的空类型,而是使用 Option<T> 作为存在值和空值间的选择,因为 Option<T> 可以被赋予指定类型,即使当变量还为初始化时,也是明确变量应该被设置的类型。

let num:Option<i32> = None;  //当变量暂不可知时,赋予None

上面的例子中,赋值为None时必须明确Option的类型,通过None是无法推断Option中值的类型的。

在上一期的《一起学Rust-实战leetcode(一)》中使用到的HashMap,其get方法获取到的就是一个Option<T>枚举类型,存在则返回Some包含的值,哈希中不存在则返回None。

Result<T,E> 枚举类型,仅有两个枚举值:

enum Result<T, E> {
    Ok(T),    //成功情况
    Err(E)    //失败情况
}

在这个枚举用的比较广泛,例如 Tcp连接的创建、文件读取、标准输入等,会存在成功或异常的情况,所以通过枚举类型携带成功或错误的信息返回。

fn main() {
    let mut input  = String::new();

//    if let Ok(string_bytes) = stdin().read_line(&mut input) {
//        println!("{}, {}", string_bytes, input);
//    } else {
//        println!("error");
//    }

    //这里写法上方的写法意义是一样的,
    let res = stdin().read_line(&mut input);
    match res {
        Ok(v) => println!("{}, {}", v,  input),
        Err(e) => println!("{}", e)
    }
}

枚举类型就介绍到这里,要想快速掌握还是应该多多练习~

觉得还不错的话就关注下吧

本文分享自微信公众号 - Rust语言学习交流(rust-china)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大道七哥

Java对象锁和类锁全面解析(多线程synchronized关键字)

本文主要是将synchronized关键字用法作为例子来去解释Java中的对象锁和类锁。特别的是希望能帮大家理清一些概念。

33920
来自专栏Java Life

请你说明一下ConcurrentHashMap的原理?

ConcurrentHashMap 类中包含两个静态内部类 HashEntry 和 Segment。HashEntry 用来封装映射表的键 / 值对;Segme...

11530
来自专栏陶士涵的菜地

[PHP] 排序和查找算法

冒泡排序的原理可以顾名思义:把每个数据看成一个气泡,按初始顺序自底向上依次对两两气泡进行比较,对上重下轻的气泡交换顺序(这里用气泡轻、重表示数据大、小),保证轻...

9320
来自专栏Java Life

请解释一下TreeMap?

TreeMap是一个有序的key-value集合,基于红黑树(Red-Black tree)的 NavigableMap实现。该映射根据其键的自然顺序进行排序,...

10130
来自专栏大道七哥

linux使用find和crontab命令定期清理过期文件

crontab 命令是 Linux 中用来设定重复执行命令或脚本的工具。它能够在指定的时间段内,按照需求以某一时间间隔执行命令或脚本。

11920
来自专栏算法工程师之路

每日算法题:Day 31(Linux)

给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8)中,按结点数值大小顺序第三小结点的值为4。

7620
来自专栏陶士涵的菜地

[javaSE] 看博客学习java并发编程

使用synchronized关键字修饰上面的addCount()方法,当前线程操作时加把锁,同时只允许一个访问者对资源进行访问,具有唯一性和排他性

6110
来自专栏陶士涵的菜地

[android] 看博客学习hashCode()和equals()

equals()是Object类提供的一个方法,众所周知,每一个java类都继承自Object,所以说每一个对象都有一个equals()方法,我们在用这个方法时...

9020
来自专栏大道七哥

正则表达式分组、断言详解

正则表达式中的断言,作为高级应用出现,倒不是因为它有多难,而是概念比较抽象,不容易理解而已,今天就让小菜通俗的讲解一下。

7120
来自专栏机器之心

PageRank、最小生成树:ML开发者应该了解的五种图算法

在互联世界中,用户不能被视为独立的实体。他们之间存在一定的关系,我们有时希望在构建机器学习模型时考虑到这些关系。

10640

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励