简单枚举
enum Ordering {
Less,
Equal,
Greater
}
在内存中,C 式枚举的值存储为整数。有时候可能要告诉 Rust 使用 什么整数:
enum HttpStatus {
Ok = 200,
NotModified = 304,
NotFound = 404,
...
}
Rust 默认使用能够容纳它们的最小内置整数类型来存储 C 式枚举。 多数情况下一个字节就够了。
use std::mem::size_of;
assert_eq!(size_of::<Ordering>(), 1);
assert_eq!(size_of::<HttpStatus>(), 2); // 一个u8装不下404
枚举也可以有方法,同样跟结构体一样:
impl TimeUnit {
/// 返回这个时间单位的复数名词
fn plural(self) -> &'static str {
match self {
TimeUnit::Seconds => "seconds",
TimeUnit::Minutes => "minutes",
TimeUnit::Hours => "hours",
TimeUnit::Days => "days",
TimeUnit::Months => "months",
TimeUnit::Years => "years"
} }
/// 返回这个时间单位的单数名词
fn singular(self) -> &'static str {
self.plural().trim_right_matches('s')
}
}
包含数据的枚举
元组变体枚举
#[derive(Copy, Clone, Debug, PartialEq)]
enum RoughTime {
InThePast(TimeUnit, u32),
JustNow,
InTheFuture(TimeUnit, u32)
}
枚举值也可以是结构体变体
enum Shape {
Sphere { center: Point3d, radius: f32 },
Cuboid { corner1: Point3d, corner2: Point3d }
}
泛型枚举
enum Result<T, E> {
Ok(T),
Err(E)
}
模式
let calendar =
match settings.get_string("calendar") {
"gregorian" => Calendar::Gregorian,
"chinese" => Calendar::Chinese,
"ethiopian" => Calendar::Ethiopian,
other => return parse_error("calendar", other)
};
other 作为一个兜底模式,与上个例子中的 n 类似。 它们都相当于 switch 语句中的 default 分支,用于匹配不与任何其 他模式匹配的值
对于引用,Rust 支持两种模式:ref 模式和 & 模式;前者借用匹配 值的元素,后者匹配引用 匹配不可复制的值会转移值
match account {
Account { name, language, .. } => {
ui.greet(&name, &language);
ui.show_settings(&account); // 错误:使用转移的值account }
}
需要一种模式来 而不转移匹配的值。关键字 ref 就是做这个用的:
match account {
Account { ref name, ref language, .. } => {
ui.greet(name, language);
ui.show_settings(&account); // 没问题 }
}
还可以使用 ref mut 借用 mut 引用
以 & 开头的模式匹配引用
match sphere.center() {
&Point3d { x, y, z } => ...
}
表达式和模式天生是相反 的。表达式 (x, y) 用两个值创建一个新元组,模式 (x, y) 则相 反:它匹配元组并将其破坏后取出两个值。对 & 而言也一样:表达式 中的 & 创建引用,模式中的 & 匹配引用
在表达式中,|是 操作符,但在这里它更像正则表达式中的 | 符号 使用 … 可以匹配某个范围中的值。范围模式包含起点值和终点值, 即 ‘0’ … ‘9’ 匹配所有 ASCII 数字:
match next_char {
'0' ... '9' =>
self.read_number(),
'a' ... 'z' | 'A' ... 'Z' =>
self.read_word(),
' ' | '\t' | '\n' =>
self.skip_whitespace(),
_ =>
}
self.handle_punctuation()
模式中的范围是 (inclusive)的,因此 ‘0’ 和 ‘9’ 都匹配 ‘0’ … ‘9’。相应地,范围表达式(中间是两个点,比如 for n in 0..100)则是半开放或 的(包含 0 但不包含 100)。之所以存在 这种不一致的现象,主要是因为互斥范围对循环和片段更有用,而全 纳范围在模式匹配中更有用
- 复习 Rust 枚举和模式 (@2024-01-22)