前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一起学Rust-枚举

一起学Rust-枚举

作者头像
江湖安得便相忘
发布2019-08-28 11:18:03
2K0
发布2019-08-28 11:18:03
举报
文章被收录于专栏:江湖安得便相忘

一、枚举定义及使用

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

代码语言:javascript
复制
enum {
    A = 'd',  //d 的 ascii码值
    B,        //e 的 ascii码值
    C,        //f 的 ascii码值
    D = 10,
    E,        //11
};

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

看一下基本的枚举定义:

代码语言:javascript
复制
//定了一个性别的枚举
enum Gender {
    Male,
    Female,
}

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

代码语言:javascript
复制
#[derive(Debug)]
enum Gender {
    Male,
    Female,
}

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

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

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

代码语言:javascript
复制
//这样是编译不通过的
if Gender::Male == "Male" {...}

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

代码语言:javascript
复制
enum ErrorLevel {
    Error(String),
    Info(String, i32),
    Warning(String),
}

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

代码语言:javascript
复制
let info = ErrorLevel::Info("info error".to_string(), 3);

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

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

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

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

三、内置常用枚举

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

代码语言:javascript
复制
#[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),
}

简化如下

代码语言:javascript
复制
enum Option<T> {
    None,
    Some(T)
}

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

代码语言:javascript
复制
let num:Option<i32> = None;  //当变量暂不可知时,赋予None

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

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

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

代码语言:javascript
复制
enum Result<T, E> {
    Ok(T),    //成功情况
    Err(E)    //失败情况
}

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

代码语言:javascript
复制
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)
    }
}

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 可回收BUG 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档