mirror of
https://github.com/gnu4cn/rust-lang-zh_CN.git
synced 2024-12-26 12:50:42 +08:00
Refining Ch06.
This commit is contained in:
parent
6bae7063bf
commit
a36eb064b2
@ -5,10 +5,12 @@
|
|||||||
|
|
||||||
结构体提供了一种将相关字段和数据,分组在一起的方法,比如有着 `width` 和 `height` 两个字段的 `Rectangle`,而枚举则提供了一种,表示一个值是一组可能值之一的方法。例如,我们可能想表达,`Rectangle` 是一组其中还包括 `Circle` 和 `Triangle` 等可能形状之一。为此,Rust 允许我们,将这些可能性编码为某个枚举。
|
结构体提供了一种将相关字段和数据,分组在一起的方法,比如有着 `width` 和 `height` 两个字段的 `Rectangle`,而枚举则提供了一种,表示一个值是一组可能值之一的方法。例如,我们可能想表达,`Rectangle` 是一组其中还包括 `Circle` 和 `Triangle` 等可能形状之一。为此,Rust 允许我们,将这些可能性编码为某个枚举。
|
||||||
|
|
||||||
我们来看看我们可能想在代码中表达的一种情况,看看为什么在这种情况下,枚举要比结构体更有用、更合适。假设我们需要处理 IP 地址。目前,IP 地址使用两种主要标准:第四版和第六版。由于我们的程序只会遇到这两种可能的 IP 地址,因此我们可以枚举所有可能的变体,这就是枚举名称的由来。
|
我们来看看我们可能想在代码中表达的一种情况,看看为什么在这种情况下,枚举要比结构体更有用、更合适。假设我们需要处理 IP 地址。目前,有两种用于 IP 地址的主要标准:版本四和版本六。由于我们的程序只会遇到这两种可能的 IP 地址,因此我们可以 *枚举出* 所有可能的变种,这就是枚举名称的由来。
|
||||||
任何 IP 地址都只能是版本四或版本六的地址,而不会同时两个都是。由于枚举值只能是枚举变种之一,那么 IP 地址的这个属性,令到枚举数据结构(the enum data structure)恰当起来。而版本四和版本六两种地址,从根本上说都是 IP 地址,那么在代码对适用于任意类别 IP 地址的情形加以处理时,版本四和版本六地址都应当作同一类型对待。
|
|
||||||
|
任何 IP 地址都可以是版本 4 或版本 6 的地址,但不能同时是这两种地址。IP 地址的这一属性,使得枚举这种数据结构非常合适,因为某个枚举值,只能是其变体之一。从根本上说,版本 4 和版本 6 地址,都仍是 IP 地址,因此当代码在处理适用于任何类别的 IP 地址的情况时,他们应被视为同一类型。
|
||||||
|
|
||||||
|
可以通过定义一个 `IpAddrKind` 枚举,并列出某个 IP 地址可以是的那些可能种类,即 `V4` 与 `V6`,我们就可以在咱们的代码中,表达这一概念。下面就是这个枚举的那些变种:
|
||||||
|
|
||||||
在代码中,可通过定义一个 `IpAddrKind` 枚举,并列出 IP 地址可能的类别,即 `V4` 和 `V6`,来表达这个概念。下面就是该枚举的变种:
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
enum IpAddrKind {
|
enum IpAddrKind {
|
||||||
@ -17,35 +19,41 @@ enum IpAddrKind {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
现在 `IpAddrKind` 就是一个可在代码中别的地方使用的定制数据类型了。
|
`IpAddrKind` 现在就是一种,我们可以在我们代码的其他地方使用的自定义数据类型。
|
||||||
|
|
||||||
|
|
||||||
## 枚举取值
|
## 枚举值
|
||||||
|
|
||||||
**Enum Values**
|
**Enum Values**
|
||||||
|
|
||||||
|
|
||||||
可像下面这样,创建出 `IpAddrKind` 两个变种的实例来:
|
我们可以像下面这样,创建出 `IpAddrKind` 两个变种的实例:
|
||||||
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let four = IpAddrKind::V4;
|
let four = IpAddrKind::V4;
|
||||||
let six = IpAddrKind::V6;
|
let six = IpAddrKind::V6;
|
||||||
```
|
```
|
||||||
|
|
||||||
请注意,该枚举的两个变种,是在其标识符的命名空间之下的,且这里使用了双冒号将标识符和变种分隔开。由于现在这两个值 `IpAddrKind::V4` 与 `IpAddrKind::V6` 都是这同一类型:`IpAddrKind`,因此这就变得有用了。随后就可以,比如,定义一个取任意 `IpAddrKind` 类型值的函数:
|
请注意,该枚举的两个变种,都是在其标识符下的命名空间中,而我们要使用双冒号,分隔两者。这很有用,因为现在 `IpAddrKind::V4` 和 `IpAddrKind::V6` 两个值,属于同一类型:`IpAddrKind`。例如,我们随后就可以定义出一个,取任意 `IpAddrKind` 的函数:
|
||||||
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn route(ip_kind: IpAddrKind) {}
|
fn route(ip_kind: IpAddrKind) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
进而就能以这两个变种对这个函数进行调用了:
|
|
||||||
|
并且我们可以两个变种,调用这个函数:
|
||||||
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
route(IpAddrKind::V4);
|
route(IpAddrKind::V4);
|
||||||
route(IpAddrKind::V6);
|
route(IpAddrKind::V6);
|
||||||
```
|
```
|
||||||
|
|
||||||
枚举的使用甚至还有更多好处。在还没有一种存储具体 IP 地址 *数据(data)* 的时候,就要进一步思考一下这里的 IP 地址类型;这是只知道 IP 地址数据为什么 *类别(king)*。根据在第 5 章中掌握的结构体知识,那么可能很想用下面清单 6-1 中的结构体来解决这个问题。
|
|
||||||
|
使用枚举还有更多优势。请再想想我们的 IP 地址类型,目前我们还没有存储具体 IP 地址 *数据* 的方法;我们只知道他是什么 *类别,kind*。鉴于咱们刚刚在第 5 章中,学习了结构体,咱们可能会想使用结构体,来解决这个问题,如下清单 6-1 所示。
|
||||||
|
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
enum IpAddrKind {
|
enum IpAddrKind {
|
||||||
@ -71,7 +79,9 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
*清单 6-1:使用结构体 `struct` 来存储 IP 地址的数据与 `IpAddrKind` 变种*
|
*清单 6-1:使用结构体 `struct` 存储 IP 地址的数据及 `IpAddrKind` 变种*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
这里已定义了有着两个字段的结构体 `IpAddr`:一个类型为 `IpAddrKind` (即先前定义的那个枚举)的 `kind` 字段,以及一个类型为 `String` 的 `address` 字段。这里有该结构体的两个实例。第一个是 `home`,而他有着与地址数据 `127.0.0.1` 关联的 `IpAddrKind::V4` 作为其 `kind` 的值。第二个实例为 `loopback`。这个实例则有不同的 `IpAddrKind` 变种作为其 `kind` 的值,即 `V6`,与 `kind` 关联的是地址 `::1`。由于这里使用了结构体将 `kind` 与 `address` 值捆绑在一起,因此现在这个 `IpAddrKind` 的变种就与那个 `String` 值关联起来了。
|
这里已定义了有着两个字段的结构体 `IpAddr`:一个类型为 `IpAddrKind` (即先前定义的那个枚举)的 `kind` 字段,以及一个类型为 `String` 的 `address` 字段。这里有该结构体的两个实例。第一个是 `home`,而他有着与地址数据 `127.0.0.1` 关联的 `IpAddrKind::V4` 作为其 `kind` 的值。第二个实例为 `loopback`。这个实例则有不同的 `IpAddrKind` 变种作为其 `kind` 的值,即 `V6`,与 `kind` 关联的是地址 `::1`。由于这里使用了结构体将 `kind` 与 `address` 值捆绑在一起,因此现在这个 `IpAddrKind` 的变种就与那个 `String` 值关联起来了。
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user