# 枚举
> [enums.md](https://github.com/rust-lang/rust/blob/master/src/doc/book/enums.md)
commit 31e39cd05c9b28c78b087aa9314f246b0b0b5cfa
Rust 中的一个`enum`是一个代表数个可能变量的数据的类型。每个变量都可选是否关联数据:
~~~
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
~~~
定义变量的语法与用来定义结构体的语法类似:你可以有不带数据的变量(像类单元结构体),带有命名数据的变量,和带有未命名数据的变量(像元组结构体)。然而,不像单独的结构体定义,一个`enum`是一个单独的类型。一个枚举的值可以匹配任何一个变量。因为这个原因,枚举有时被叫做“集合类型”:枚举可能值的集合是每一个变量可能值的集合的总和。
我们使用`::`语法来使用每个变量的名字:它们包含在`enum`名字自身中。这样的话,以下的情况都是可行的:
~~~
# enum Message {
# Move { x: i32, y: i32 },
# }
let x: Message = Message::Move { x: 3, y: 4 };
enum BoardGameTurn {
Move { squares: i32 },
Pass,
}
let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 };
~~~
这两个变量都叫做`Move`,不过他们包含在枚举名字中,他们可以无冲突的使用。
枚举类型的一个值包含它是哪个变量的信息,以及任何与变量相关的数据。这有时被作为一个“标记的联合”被提及。因为数据包括一个“标签”表明它的类型是什么。编译器使用这个信息来确保安全的访问枚举中的数据。例如,我们不能简单的尝试解构一个枚举值,就像它是其中一个可能的变体那样:
~~~
fn process_color_change(msg: Message) {
let Message::ChangeColor(r, g, b) = msg; // compile-time error
}
~~~
不支持这些操作(比较操作)可能看起来更像限制。不过这是一个我们可以克服的限制。有两种方法:我们自己实现相等(比较),或通过[`match`](#)表达式模式匹配变量,你会在下一部分学到它。我们还不够了解Rust如何实现相等,不过我们会在[特性](#)找到它们。
### 构造器作为函数(Constructors as functions)
一个枚举的构造器总是可以像函数一样使用。例如:
~~~
# enum Message {
# Write(String),
# }
let m = Message::Write("Hello, world".to_string());
~~~
与下面是一样的:
~~~
# enum Message {
# Write(String),
# }
fn foo(x: String) -> Message {
Message::Write(x)
}
let x = foo("Hello, world".to_string());
~~~
这对我们没有什么直接的帮助,直到我们要用到[闭包](#)时,这时我们要考虑将函数作为参数传递给其他函数。例如,使用[迭代器](#),我们可以这样把一个`String`的vector转换为一个`Message::Write`的vector:
~~~
# enum Message {
# Write(String),
# }
let v = vec!["Hello".to_string(), "World".to_string()];
let v1: Vec<Message> = v.into_iter().map(Message::Write).collect();
~~~
- 前言
- 贡献者
- 1.介绍
- 2.准备
- 3.学习 Rust
- 3.1.猜猜看
- 3.2.哲学家就餐问题
- 3.3.其它语言中的 Rust
- 4.语法和语义
- 4.1.变量绑定
- 4.2.函数
- 4.3.原生类型
- 4.4.注释
- 4.5.If语句
- 4.6.循环
- 4.7.所有权
- 4.8.引用和借用
- 4.9.生命周期
- 4.10.可变性
- 4.11.结构体
- 4.12.枚举
- 4.13.匹配
- 4.14.模式
- 4.15.方法语法
- 4.16.Vectors
- 4.17.字符串
- 4.18.泛型
- 4.19.Traits
- 4.20.Drop
- 4.21.if let
- 4.22.trait 对象
- 4.23.闭包
- 4.24.通用函数调用语法
- 4.25.crate 和模块
- 4.26.const和static
- 4.27.属性
- 4.28.type别名
- 4.29.类型转换
- 4.30.关联类型
- 4.31.不定长类型
- 4.32.运算符和重载
- 4.33.Deref强制多态
- 4.34.宏
- 4.35.裸指针
- 4.36.不安全代码
- 5.高效 Rust
- 5.1.栈和堆
- 5.2.测试
- 5.3.条件编译
- 5.4.文档
- 5.5.迭代器
- 5.6.并发
- 5.7.错误处理
- 5.8.选择你的保证
- 5.9.外部函数接口
- 5.10.Borrow 和 AsRef
- 5.11.发布途径
- 5.12.不使用标准库
- 6.Rust 开发版
- 6.1.编译器插件
- 6.2.内联汇编
- 6.4.固有功能
- 6.5.语言项
- 6.6.链接进阶
- 6.7.基准测试
- 6.8.装箱语法和模式
- 6.9.切片模式
- 6.10.关联常量
- 6.11.自定义内存分配器
- 7.词汇表
- 8.语法索引
- 9.参考文献
- 附录:名词中英文对照