概要
枚举(Enumeration)是一种数据类型,用于定义一个值的有限集合。
枚举类型可以包含多个不同类型的值,这些值可以是具体的数据类型或自定义结构体类型。
语法
enum enum_name {
variant1,
variant2,
variant3
}
定义一个枚举
//定义一个IpAddrKind枚举,并列出IP地址类型,V4和V6,也是枚举的成员(variants):
enum IpAddrKind {
V4,
V6,
}
现在IpAddrKind 就是一个可以在代码中使用的自定义数据类型了。
枚举使用的语法
enum_name::variant
枚举值
//创建IpAddrKind两个不同成员的实例
let four = IpAddrKind::V4;
let six = IpAddrKind::V6;
定义一个函数来获取任何IpAddrKind
fn route(ip_kind: IpAddrKind) {}
使用任一成员调用这个函数
route(IpAddrKind::V4);
route(IpAddrKind::V6);
示例一:
加入我们要访问一台主机,可以通过主机名访问,也可以通过IP地址访问。像同一天只可能是WeekDay中一个一样,同一次访问只能选择主机名或IP其中之一。
#[derive(Debug)]
enum AddrType {
Domain,
IP
}
#[derive(Debug)]
struct Addr {
addrtype: AddType,
addr: String
}
fn main() {
let host = Addr {
addrtype: AddrType::Domain,
addr: String::from("localhost")
};
println!("host is {:?}", host);
}
以上还是一般枚举的思路,我们还有捷径可以利用:
#[derive(Debug)]
enum Addr {
Domain(String),
IP(u8, u8, u8, u8)
}
fn main() {
let host = Addr::IP(127, 0., 0, 1);
println!("host is {:?}", host);
}
枚举中可以任意的类型,而且每个枚举项可以是不同的类型。
示例二:
将IP地址的数据和IpAddrKind成员存储在一个struct中
enum IpAddrKind {
V4,
V6,
}
struct IpAddr {
kind: IpAddrKind,
address: String,
}
let home = IpAddr {
kind: IpAddrKind::V4;
address: String::from("127.0.0.1"),
};
let loopback = IpAddr {
kind: IpAddrKind::V6,
address: String::from("::1");
};
使用一种更简洁的方式来表达相同的概念,仅仅使用枚举并将数据直接放进每一个枚举成员而不是将枚举作为结构体的一部分。
IpAddr枚举的新定义表明了V4和V6成员都关联了String值:
enum IpAddr {
V4(String),
V6(String),
}
let home = IpAddr::V4(String::from("127.0.0.1"));
let loopback = IpAddr::V6(String::from("::1"));
我们直接将数据附加到枚举的每个成员上,这样就不需要一个额外的结构体了。我们定义的每一个枚举成员的名字变成了一个构建枚举的实例的函数。换言之,IpAddr::V4()是一个获取String参数并返回IpAddr类型实例的函数调用。作为定义枚举的结果,这些构造函数会自动被定义。
用枚举替代结构体的另一个优势:每个成员可以处理不同类型和数量的数据。
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1");
内置的枚举
Option
Rust标准库中有一个内置的枚举类型Option,被广泛应用与需要处理空值的地方。
enum Option<T> {
Some(T),
None,
}
Rust对其进行了特殊处理,不需要引用而直接使用Some(T),而不使用Option::Some(T)。< T>接受任意类型的参数。
let some_number = Some(5);
let some_string = Some("a string");
因为省略了Option::,所以看上去创建一个Some对象,实际上它是一个Option<T>枚举的成员。
如果成员的类型是None,则必做指明<T>的具体类型:
let absent_number: Option<i32> = None;
Result
Result是Rust内置的另一个枚举,通常被用于错误处理,定义如下:
enum Result<T, E> {
Ok(T),
Err(E),
}
与Option的<T,E>,T代表正常情况下Ok成员的值,而E代表错误发生时Err成员的值。
use std::fs::File;
fn main() {
let f = File::open("hello.txt");
match f {
Ok(file) => println!("open file success"),
Err(error) => println!("open file error: {:?}", error)
};
}