枚举
类C的枚举类型会在内存里存成整型,且Rust会用最小的能够存放的类型来存。可以用#[repr]
指定其内存形式。使用的时候用as
进行类型转换也是可以的。但是不能从其它类型转成枚举,只能自己写转换逻辑或者使用crate enum_primitive。
对应结构体,枚举的成员也有三种类型:结构体型,元组型和单元型。
成员的可见性和枚举本身一致。
在内存里,有数据的enum会保存一个小整型作为标签,加上能够容纳最大的成员的内存。标签是给Rust内部用来识别是哪个成员的。但Rust不保证内存结构。
use std::collections::HashMap;
enum Json {
Null,
Boolean(bool),
Number(f64),
String(String),
Array(Vec<Json>),
Object(Box<HashMap<String, Json>>),
}
上例中使用Box是为了让内存更紧致(compact,压缩,整齐),因为enum在内存里要能放下最大的那个成员,如果不用指针而是放实际的对象,则会占用很大的内存。
在泛型枚举(generic enum)中,像Option
模式
Pattern type | Example | Notes |
---|---|---|
Literal | 100 “name” |
Matches an exact value; the name of a const is also allowed |
Range | 0 ..= 100 ‘a’ ..= ‘k’ |
Matches any value in range, including the end value |
Wildcard | _ | Matches any value and ignores it |
Variable | name mut count |
Like _ but moves or copies the value into a new local variable |
ref variable | ref field ref mut field |
Borrows a reference to the matched value instead of moving or copying it |
Binding with subpattern | val @ 0 ..= 99 ref circle @ Shape::Circle { .. } |
Matches the pattern to the right of @, using the variable name to the left |
Enum pattern | Some(value) None Pet::Orca |
|
Tuple pattern | (key, value) (r, g, b) |
|
Array pattern | [a, b, c, d, e, f, g] [heading, carom, correction] |
|
Slice pattern | [first, second] [first, _, third] [first, .., nth] [] |
|
Struct pattern | Color(r, g, b) Point { x, y } Card { suit: Clubs, rank: n } Account { id, name, .. } |
|
Reference | &value &(k, v) |
Matches only reference values |
Multiple patterns | ‘a’ | ‘A’ | In refutable patterns only (match, if let, while let) |
Guard expression | x if x * x <= r2 | In match only (not valid in let, etc.) |
匹配结构的时候可以用..省略不关心的字段。
匹配切片的时候不仅匹配值还可以匹配长度,..也可以用来省略元素。
match
的值在匹配的分支会转移不能Copy
的类型,使用ref
可以借用引用,而不转移。
#[derive(Debug)]
struct S {
a: String,
b: String
}
fn main() {
let s = S {a: "1".into(), b: "2".into()};
match s {
S{ref a, ref b} => println!("{}, {}", a, b),
_ => {}
}
println!("{:#?}", s) // 如果不用ref这里会报错:borrow of partially moved value: `s`
}
可见match
本身并不会转移,而是在具体的分支才会,但如果match
处就借用&s
,分支处也不用ref
了。(因为有Binding modes,如果match的本身是引用,匹配到变量会自动变成引用)ref mut
可以从匹配分支获取可变引用。
匹配条件里的变量是重新声明的,会shadow其它同名的变量。
在match
条件后还可以再家if
判断来进行更具体的判断,被称为match guard。|
可以表示或,在一个条件中匹配其中一个就算匹配。..=
用来匹配范围:1..=9
,'a'..='z'
,开区间匹配是不允许的。@
用来给匹配赋值s1 @ S{..} =>
,x @ 1..=9 =>
。
模式匹配还可以用来,定义变量,传递参数,for循环。用来解构struct,tuple和map。用在这些地方的模式只能是irrefutable的,match
,if let
和while let
中可以用refutable的。