枚举与模式匹配
枚举允许我们列举所有可能性的值来定义一个类型
定义枚举
enum IpAddKind {
V4,
V6,
}
fn main() {
let four = IpAddKind::V4;
let six = IpAddKind::V6;
route(four);
route(six);
route(IpAddKind::V4);
route(IpAddKind::V6);
}
fn route(ip_kind: IpAddKind) {
}
定义变体
enum IpAddrKind {
V4,
V6,
}
struct IpAddr {
kind: IpAddrKind,
address: String,
}
fn main() {
let home = IpAddr {
kind: IpAddrKind::V4,
address: String::from("127.0.0.1")
};
let loopback = IpAddr {
kind: IpAddrKind::V6,
address: String::from("::1")
};
}
枚举的变体
- 优点:
- 不需要额外使用
struct
- 每个变体可以拥有不同的类型以及关联的数据量
- 不需要额外使用
enum IpAddr {
V4(u8, u8, u8, u8),
V6(String),
}
fn main() {
let home = IpAddr::V4(127, 0, 0, 1);
let loopback = IpAddr::V6(String::from("::1"));
}
标准库中的 IpAddr
struct Ipv4Addr {
// snip
}
struct Ipv6Addr {
// snip
}
enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr)
}
变体的案例
enum Message {
Quit, // 没有关联任何数据
Move { x: i32, y: i32 }, // 包含了匿名结构体
Write(String),
ChangeColor(i32, i32, i32),
}
fn main() {
let q = Message::Quit;
let m = Message::Move {x: 12, y:24};
let w = Message::Write(String::from("hello world"));
let c = Message::ChangeColor(0,0,0);
}
为枚举定义方法
- 也使用
impl
关键字
enum Message {
Quit, // 没有关联任何数据
Move { x: i32, y: i32 }, // 包含了匿名结构体
Write(String),
ChangeColor(i32, i32, i32),
}
impl Message {
fn call(&self) {}
}
fn main() {
let q = Message::Quit;
let m = Message::Move { x: 12, y: 24 };
let w = Message::Write(String::from("hello world"));
let c = Message::ChangeColor(0, 0, 0);
m.call()
}
Option 枚举
- 定义在标准库
- 在 prelude (预导入模块)中
- 描述了:某个值可能存在(某种类型)或不存在的情况
注意这个价值数十亿美刀的错误设计
Rust
没有Null
。在其他语言可以表示空值 或者 空指针。- 一个变量可以处于两种状态:空值(null)、非空。
- Null 引用:作者开演讲会的时候说过一句话 Billion Dollar Mistake。
- Null 的问题在于:当你尝试像使用非 Null 值那样使用 Null 值的时候,就会引起某种错误。
- Null 的概念还是有效的:因某种原因而变为无效或者缺失的值。
因此 Rust 才出现类似 Null 概念的一个枚举 Option<T>
- 标准库中的定义
enum Option<T> {
Some(T),
None
}
- 它包含在
Prelude
(预导入模块)中。可直接使用:- Option
<T>
- Some
<T>
- None
- Option
案例
fn main() {
// 有效值
let some_number = Some(5);
let some_thing = Some(5);
// 无效值
let absent_number: Option<i32> = None;
}
Option<T> 比 Null 好在哪?
// Option<T> 和 T 是不同的类型,不可以把 Option<T> 直接当成 T 来使用
fn main() {
let x:i8 = 5;
let y: Option<i8> = Some(5);
// 若想使用 Option<T> 中的 T, 必须将它转换为 T 也就是把 y 转换为 i8
// 在 C# 中:
// string a = null;
// string b = a + '123456';
let sum = x + y;
}