枚举

定义

Variants can be accessed through :: notation, ex. Day::Sunday
通过双冒号 :: 访问枚举成员

⭐️ Each enum variant can have,

  • No data (unit variant)
  • Unnamed ordered data (tuple variant)
  • Named data (struct variant)

枚举成员的类型:

  • 单元结构体
  • 元组结构体
  • C结构体

示例:

  1. enum FlashMessage {
  2. Success, // 1.单元类型成员
  3. Warning { category: i32, message: String }, // 2.结构体类型成员
  4. Error(String), // 3.元组类型成员
  5. }
  6. fn main() {
  7. // 1.单元类型成员
  8. let mut form_status = FlashMessage::Success;
  9. print_flash_message(form_status);
  10. // 2.结构体类型成员
  11. form_status = FlashMessage::Warning {
  12. category: 2,
  13. message: String::from("Field X is required"),
  14. };
  15. print_flash_message(form_status);
  16. 3.元组类型成员
  17. form_status = FlashMessage::Error(String::from("Connection Error"));
  18. print_flash_message(form_status);
  19. }
  20. fn print_flash_message(m: FlashMessage) {
  21. // 对于枚举的模式匹配
  22. match m {
  23. FlashMessage::Success => println!("Form Submitted correctly"),
  24. FlashMessage::Warning { category, message } =>
  25. // 用相同的属性名解构
  26. {
  27. println!("Warning : {} - {}", category, message)
  28. }
  29. FlashMessage::Error(msg) => println!("Error : {}", msg),
  30. }
  31. }

枚举的方法

可以使用impl来为枚举上定义方法:

  1. fn main() {
  2. #[derive(Debug)]
  3. enum Message {
  4. Quit,
  5. Move { x: i32, y: i32 },
  6. Write(String),
  7. ChangeColor(i32, i32, i32),
  8. }
  9. impl Message {
  10. fn call(&self) {
  11. println!("{:?}", self)
  12. }
  13. }
  14. let m = Message::Write(String::from("hello"));
  15. m.call();
  16. }

方法中的self指向变量m

枚举也可以有关联函数

Option枚举

空值问题在于当你尝试像一个非空值那样使用一个空值,会出现某种形式的错误

然而,空值尝试表达的概念仍然是有意义的:空值是一个因为某种原因目前无效或缺失的值

Rust 并没有空值,不过它确实拥有一个可以编码存在或不存在概念的枚举。这个枚举是 Option<T>,而且它定义于标准库中,如下:

  1. enum Option<T> {
  2. Some(T),
  3. None,
  4. }

Option<T>枚举包含在了prelude之中,可以直接使用**Option<T>**和其成员**Some()****None**

如果只使用None而不是Some,需要告诉Rust``Option<T>是什么类型的

Option<T>T(这里T可以是任何类型)是不同的类型,因此即使Some()中有值,也不能直接使用,而是需要使用**match**表达式Some()None指定各自的处理代码。这样就能考虑到值存在和不存在的情况,而不是直接假设值存在

match控制流

=>运算符将模式和将要运行的代码分开

每个分支相关联的代码是一个表达式(即花括号这样的语句块叫做表达式),而表达式的结果值将作为整个match表达式的返回值。

Rust中的匹配是穷尽的exhaustive):必须穷举到最后的可能性来使代码有效。

**_** 通配符
示例:

  1. let some_u8_value = 0u8;
  2. match some_u8_value {
  3. 1 => println!("one"),
  4. 3 => println!("three"),
  5. _ => (),
  6. }

if let语句

if let用来处理只匹配一个模式的值而忽略其他模式的情况,是match的一个语法糖

if let没有返回值

这会失去match强制要求的穷尽性检查

if let获取通过等号分隔的一个模式和一个表达式
示例:

  1. if let Some(3) = some_u8_value {
  2. println!("three");
  3. }

可以搭配**else**语句来用,用于匹配所有其他情况,相当于match中的通配符_
示例:

  1. let mut count = 0;
  2. if let Coin::Quarter(state) = coin {
  3. println!("State quarter from {:?}!", state);
  4. } else {
  5. count += 1;
  6. }