Rust 学习笔记(10)-枚举

本篇是阅读 《Rust 程序设计语言》第6.1章 枚举 而来的结果

枚举是一个很多语言都有的功能,不过不同语言中其功能各不相同,Rust中的枚举允许你通过列举可能的成员(variants)来定义一个类型

枚举主要作用是限制传入或传出的类型,避免出现其他类型,这在Rust中有一个著名的枚举 Option 我们稍后会学习

示例代码1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 下面的实例定义了一个枚举类型
#[derive(Debug)]
enum IpAddrKind {
    V4,
    V6,
}

// 定义一个结构体,用于和枚举类型相关联
#[derive(Debug)]
struct IpAddr {
    kind: IpAddrKind, // 接受IpAddrKind枚举类型
    address: String,
}

fn main() {
    // 我们将枚举和String类型关联
    // 这里我们定义了一个有两个字段的结构体 IpAddr 一个是 IpAddrKind(之前定义的枚举)类型的 kind 字段,一个是 String 类型 address 字段
    // 我们有一个结构体的实例home,它的 kind 的值是 IpAddrKind::V4 与之相关联的地址数据是 127.0.0.1。
    // 我们通过结构体 IpAddr 来将 kind 和 address 打包在一起,现在枚举成员就与值相关联了。
    let home = IpAddr {
        kind: IpAddrKind::V4,
        address: String::from("127.0.0.1"),
    };
    println!("{:?}", home);
}

上面的方式有点麻烦,我们需要定义一个结构体,手动关联它,我们还有更方便的方式
我们直接将数据附加到枚举的每个成员上,这样就不需要一个额外的结构体了,请看下面示例代码2

示例代码2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#[derive(Debug)]
enum IpAddr {
    V4(String),
    V6(String),
}

fn main() {
    // 我们可以使用一种更简洁的方式来表达相同的概念,
    // 仅仅使用枚举并将数据直接放进每一个枚举成员而不是将枚举作为结构体的一部分。
    let home = IpAddr::V4(String::from("127.0.0.1"));
    println!("{:?}", home);
}

这里也很容易看出枚举工作的另一个细节:每一个我们定义的枚举成员的名字也变成了一个构建枚举的实例的函数。
也就是说,IpAddr::V4() 是一个获取 String 参数并返回 IpAddr 类型实例的函数调用。作为定义枚举的结果,这些构造函数会自动被定义。

用枚举替代结构体还有另一个优势:每个成员可以处理不同类型和数量的数据,请看示例代码3

示例代码3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 枚举成员可以关联不同的类型
#[derive(Debug)]
enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}

fn main() {
    // 用枚举替代结构体还有另一个优势:每个成员可以处理不同类型和数量的数据。
    // IPv4 版本的 IP 地址总是含有四个值在 0 和 255 之间的数字部分。
    // 如果我们想要将 V4 地址存储为四个 u8 值而 V6 地址仍然表现为一个 String,
    // 这就不能使用结构体了。枚举则可以轻易的处理这个情况:
    let home = IpAddr::V4(127, 0, 0, 1);
    println!("{:?}", home);
}

最后提一嘴,我们在枚举上还可以定义方法

1
2
3
4
5
impl IpAddr {
    fn print(&self) {
        println!("{:?}", self)
    }
}
updatedupdated2025-03-012025-03-01