一、枚举定义及使用
枚举的定义在其他许多的语言中都有实现,举例来说,比如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)
}
}
枚举类型就介绍到这里,要想快速掌握还是应该多多练习~
觉得还不错的话就关注下吧
完