一起學Rust-枚舉

  • 2019 年 10 月 6 日
  • 筆記

一、枚舉定義及使用

枚舉的定義在其他許多的語言中都有實現,舉例來說,比如C中的枚舉,枚舉值在未賦值的情況下默認從0開始遞增或從上一個枚舉值開始遞增,值類型可以是整數或字元類型,實質只能保存整型:

enum {      A = 'd',  //d 的 ascii碼值      B,        //e 的 ascii碼值      C,        //f 的 ascii碼值      D = 10,      E,        //11  };

Rust中的枚舉與C中的枚舉不同,功能非常強大,可以用枚舉表達更多的可能性數據。

看一下基本的枚舉定義:

//定了一個性別的枚舉  enum Gender {      Male,      Female,  }

這裡面不同的是,Male和Female不是變數,而是枚舉值,而不像是C中會訪問到相應的數字。

#[derive(Debug)]  enum Gender {      Male,      Female,  }    println!("{:?}, {:?}", Gender::Male, Gender::Female);    ----- 輸出 -----  Male, Female

雖然輸出看上去是字元串類型,但實際是枚舉Gender類型

//這樣是編譯不通過的  if Gender::Male == "Male" {...}

枚舉值的代數形式是可以與實際的值進行結合的,而且是可以結合不同類型的數據,這使得枚舉的能力更強:

enum ErrorLevel {      Error(String),      Info(String, i32),      Warning(String),  }

每一個枚舉值可可以放入不同類型的數據,作為枚舉的一部分,那麼通過下面的例子看一下如何定義帶數據的枚舉值:

let info = ErrorLevel::Info("info error".to_string(), 3);    match info {      ErrorLevel::Info(k, v)  => {          println!("{}, {}", k, v);      },      _ => ()  }

上面的例子裡面通過模式匹配獲取了Info枚舉值內的數據,這裡需要注意的是上面的例子在match程式碼塊後方就不能再使用info的變數了,這裡涉及到Rust中所有權的特性,也是Rust中非常重要的特性,這裡暫不過多的探討。

不過上面的例子僅支援固定類型的值,對於不同級別的錯誤日誌來說,有些時候會需要記錄一些不同類型的數據,所以可能需要不同的參數類型(這樣說稍微牽強),看下面枚舉結合 泛型 的例子:

enum ErrorLevel<T> {      Error(T),      Info(T),      Warning(T),  }  let info = ErrorLevel::Info("abc");  //可以通過自動推斷類型  let info = ErrorLevel::<&str>::Info("abc");  //可以指定類型並賦值

三、內置常用枚舉

Option<T> 枚舉類型,通過IDE可以查看它的完整定義:

#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]  #[stable(feature = "rust1", since = "1.0.0")]  pub enum Option<T> {      /// No value      #[stable(feature = "rust1", since = "1.0.0")]      None,      /// Some value `T`      #[stable(feature = "rust1", since = "1.0.0")]      Some(#[stable(feature = "rust1", since = "1.0.0")] T),  }

簡化如下

enum Option<T> {      None,      Some(T)  }

Option<T> 是一個非常重要的枚舉類型,在程式中無需引用庫,直接可以使用Some(T)和None。另外一個原因是因為Rust中去除了空類型,也就是沒有null、nil、none、這種在其他語言中非常常見的空類型,而是使用 Option<T> 作為存在值和空值間的選擇,因為 Option<T> 可以被賦予指定類型,即使當變數還為初始化時,也是明確變數應該被設置的類型。

let num:Option<i32> = None;  //當變數暫不可知時,賦予None

上面的例子中,賦值為None時必須明確Option的類型,通過None是無法推斷Option中值的類型的。

在上一期的《一起學Rust-實戰leetcode(一)》中使用到的HashMap,其get方法獲取到的就是一個Option<T>枚舉類型,存在則返回Some包含的值,哈希中不存在則返回None。

Result<T,E> 枚舉類型,僅有兩個枚舉值:

enum Result<T, E> {      Ok(T),    //成功情況      Err(E)    //失敗情況  }

在這個枚舉用的比較廣泛,例如 Tcp連接的創建、文件讀取、標準輸入等,會存在成功或異常的情況,所以通過枚舉類型攜帶成功或錯誤的資訊返回。

fn main() {      let mut input  = String::new();    //    if let Ok(string_bytes) = stdin().read_line(&mut input) {  //        println!("{}, {}", string_bytes, input);  //    } else {  //        println!("error");  //    }        //這裡寫法上方的寫法意義是一樣的,      let res = stdin().read_line(&mut input);      match res {          Ok(v) => println!("{}, {}", v,  input),          Err(e) => println!("{}", e)      }  }

枚舉類型就介紹到這裡,要想快速掌握還是應該多多練習~

覺得還不錯的話就關注下吧