Skip to main content

枚举与模式匹配

枚举允许我们列举所有可能性的值来定义一个类型

定义枚举

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
案例
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;
}