Rust - enum基本使用

这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战

枚举enumerations),也被称作 enums。枚举允许你通过列举可能的 成员variants) 来定义一个类型。

枚举是一个很多语言都有的功能,不过不同语言中其功能各不相同。Rust 的枚举与 F#、OCaml 和 Haskell 这样的函数式编程语言中的 代数数据类型algebraic data types)最为相似。

定义枚举

上面介绍什么是枚举,那么为什么要使用枚举呢?我们知道枚举可以用来列出所有可能的值,比如我们要处理IP地址,目前被广泛使用的两个主要 IP 标准:IPv4(version four)和 IPv6(version six)。任何一个 IP 地址要么是 IPv4 的要么是 IPv6 的,而且不能两者都是。IP 地址的这个特性使得枚举数据结构非常适合这个场景,因为枚举值只可能是其中一个成员。IPv4 和 IPv6 从根本上讲仍是 IP 地址,所以当代码在处理适用于任何类型的 IP 地址的场景时应该把它们当作相同的类型。

基于上面的情况,我们就可以在代码中定义一个IPAddr枚举来表现这个概念并列出可能的IP地址类型,IP地址类型v4 v6就被称为枚举的 成员variants),此时IPAddr就是一个可以在代码中使用的自定义数据类型了:

enum IPAddr {
    v4,  // 枚举中的不同成员使用,隔开
    v6,
}
复制代码

枚举值

有了IPAddr之后,可以在代码中创建不同成员的实例,如下代码:

enum IPAddr {
    v4,  // 枚举中的不同成员使用,隔开
    v6,
}

fn main() {
    let four = IPAddr::v4;
    let six = IPAddr::v6;
}
复制代码

使用枚举有很多的好处,比如目前没有一个存储实际 IP 地址 数据 的方法;只知道它是什么 类型 的。基于前面文章提到的结构体,可以像下述代码这样处理这个需求:

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"),
};
复制代码

这里我们定义了一个有两个字段的结构体 IpAddrIpAddrKind(之前定义的枚举)类型的 kind 字段和 String 类型 address 字段,使用了一个结构体来将 kindaddress 打包在一起,现在枚举成员就与值相关联了。

其实可以使用一种更加简洁的方式表达相同的概念,就是仅使用枚举并将数据直接放进每一个枚举成员而不是将枚举作为结构体的一部分。IpAddr 枚举的新定义表明了 V4V6 成员都关联了 String 值,如下代码示例:

enum IpAddr {
    V4(String),
    V6(String),
}

let home = IpAddr::V4(String::from("127.0.0.1"));

let loopback = IpAddr::V6(String::from("::1"));
复制代码

直接将数据附加到枚举的每个成员上,这样就不需要一个额外的结构体了。

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

enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}

let home = IpAddr::V4(127, 0, 0, 1);

let loopback = IpAddr::V6(String::from("::1"));
复制代码

结语

文章首发于微信公众号程序媛小庄,同步于掘金

码字不易,转载请说明出处,走过路过的小伙伴们伸出可爱的小指头点个赞再走吧(╹▽╹)

猜你喜欢

转载自juejin.im/post/7035888988107833374
今日推荐