声明枚举:
enum
枚举变体:
枚举元素
枚举和枚举变体关系:
枚举的变体全都位于其标识符的命名空间;枚举变体拥有相同的类型-枚举类型。
枚举变体的访问:
使用两个冒号
enum IpAddrKind{
V4,
V6,
}
IpAddrKind::V4
数据嵌入枚举变体内:
enum IpAddr{
V4(String),
V6(String),
}
枚举定义这里定义的是数据的类型。枚举使用的时候需要指定枚举变体的数据:
let home = IpAddr::V4(String::from("127.0.0.1");
使用枚举代替结构体的优势在于,每个变体可以拥有不同类型和数量的关联数据:
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
注:可以在枚举的变体中嵌入任意类型的数据,字符串、数值,结构体,甚至可以嵌入另外一个枚举
enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr),
}
Ipv4Addr是一个struct
枚举比结构体的优势:
结构体需要定义多个,每个结构体都是一个类型;枚举可以包含多个枚举变体,且类型都是枚举。
enum Message{
Quit,
Move {x:i32,y:i32},
write(String),
ChangeColor(i32,i32,i32)
}
struct QuitMessage;
struct MoveMessage{
x:i32,
y:i32,
}
struct WriteMessage(String);
struct ChangeColorMessage(i32,i32,i32);
定义枚举的方法:
#[derive(Debug)]
enum Message{
Quit,
Move {x:i32,y:i32},
write(String),
ChangeColor(i32,i32,i32)
}
impl Message{
fn call(&self){
println!("{:?}",self);
}
}
这里的self就是指向媒体变体。不要和struct弄混了,不可以通过0,1,2访问枚举变体里的值。
Option<T>枚举:
使用Option<T> 而不直接使用None的原因:
使用空值的常见的问题是:假设某个值存在,但实际上却为空。会造成业务代码逻辑的错误。
Option<T> 使用场景:
当持有一个可能为空(存在为空的可能性)的值的时候。只要一个值的类型不是Option<T>,我们就可以安全假设这个值是非空的。
取出Some变体中的值:
1. match表达式
总结:处理Option<T>值的时候,必须要编写处理每个变体的代码。
match控制流:
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
match coin {
❸ Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
match,它允许将一个值与一系列的模式相比较,并根据匹配的模式执行相应代码
其中,模式指的是match模块中的Coin::Penny,如果coin是该枚举变体,那么就会执行后面的代码。其他模式可以是模字面量、变量名、通配符等。
通过match可以取出Some变体中的值:
fn plus_one(x:Option<i32>) -> Option<i32>{
match x{
Some(i) => Some(i+1),
None=>None
}
}
match匹配必须穷举所有的可能。如果不想穷尽,则使用_通配符,表示剩余的部分:
let some_u8_value = 0u8;
match some_u8_value {
1 => println!("one"),
3 => println!("three"),
5 => println!("five"),
7 => println!("seven"),
_ => (),
}
if let控制流:
只关心某一种特定可能的情形下,if let 中只有一个“=” 号:
let some_u8_value = Some(0u8);
f let Some(3) = some_u8_value {
println!("three");
}
可以在if let中搭配使用else:
let mut count = 0;
if let Coin::Quarter(state) = coin {
println!("State quarter from {:?}!", state);
} else {
count += 1;
}