以下内容为本人学习过程中的记录笔记,其中可能存在不准确或错误,欢迎勘误及指正

枚举的基本操作

在Rust中,枚举类型是一种通过enum关键字定义的特殊的类型,允许用户定义一个取值范围有限的变量

定义枚举

一个枚举可以包含一系列命名的值,这些值就被称为枚举成员(enumeration variant)

1
2
3
4
5
6
7
8
9
10
11
12
// 定义枚举
enum Species {
Human,
Animal,
Plant,
}

fn main() {
// 创建枚举变量
let john = Species::Human;
let tom = Species::Animal;
}

枚举类型作为自定义数据类型,和其他的数据类型一样,枚举变量也可以通过函数进行传递或作为结构体字段类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
enum Species {
Human,
Animal,
Plant,
}

// 作为结构体字段类型
struct Earth {
leader: Species,
member: String,
}

fn main() {
let john = Species::Human;
let tom = Species::Animal;

// 在函数间传递
sleep(john);
sleep(tom);
sleep(Species::Animal);
}

fn sleep(species: Species) {}

枚举成员可以是一个简单的标识符,也可以包含数据或者匿名结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum Species {
Human(String),
Animal(String),
Plant(String),
Alien { name: String, attitude: String },
}

fn main() {
let john = Species::Human("Male".to_string());
let tom = Species::Animal("Cat".to_string());
let tiga = Species::Alien {
name: "Ultraman".to_string(),
attitude: "Friendly".to_string(),
};
}

枚举方法

和结构体类似,枚举也可以使用impl定义其关联的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
enum Species {
Human(String),
Animal(String),
Plant(String),
Alien { name: String, attitude: String },
}

impl Species {
fn war(&self) {
// 使用模式匹配解构枚举变量
match self {
Species::Alien { name, attitude } if attitude == "Hostile" => {
println!("{} is a threat, Start War!", name);
}
_ => {
println!("Friendly!");
},
}
}
}

fn main() {
let tiga = Species::Alien {
name: "Ultraman".to_string(),
attitude: "Friendly".to_string(),
};
let thanos = Species::Alien {
name: "Eternals".to_string(),
attitude: "Hostile".to_string(),
};
tiga.war();
thanos.war();
}

枚举的解构

当我们想使用枚举中的值或针对特定枚举执行相应的操作时,就需要通过模式匹配(pattern matching)来解构枚举。具体来说,可以使用matchif let表达式,将枚举变量与每个可能的值进行比较,并执行相应的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
enum Species {
Quit,
Human(String),
Animal(String),
Plant(String),
}

fn main() {
let flag = Species::Quit;
let person = Species::Human("john".to_string());
let cat = Species::Animal("tom".to_string());
let chaos = Species::Human("jeff".to_string());

// 使用match匹配所有条件
let person_name = match person {
Species::Human(name) => name,
Species::Plant(name) => name,
Species::Animal(name) => name,
Species::Quit => "No Person".to_string(),
};

// 使用if let匹配单个条件
let chaos_name = if let Species::Plant(name) = chaos {
name
} else if let Species::Animal(name) = chaos {
name
} else {
"chaos Unknown!".to_string()
};

// 使用"_"通配符匹配其余所有条件
let animal_name = match cat {
Species::Animal(name) => Some(name),
_ => None,
};

if let Species::Quit = flag {}

println!("{}", person_name);
println!("{:?}", animal_name);
println!("{}", chaos_name);
}

由上面例子可以看出来,使用match对枚举进行解构时需列举所有的可能情况,但我们也可以使用_通配符来简化匹配;if let则只适用于匹配单个模式的情况,但可配合使用elseelse if let来匹配多个模式