rust-quiz:007-surprise-wildcard-match.rs

godme發表於2022-07-08
#[repr(u8)]
enum Enum {
    First,
    Second,
}

impl Enum {
    fn p(self) {
        match self {
            First => print!("1"),
            Second => print!("2"),
        }
    }
}

fn main() {
    Enum::p(unsafe {
        std::mem::transmute(1u8)
    });
}
  • #[repr(u8)]
    rust的記憶體佈局layer不用在意,這裡只要知道這是按照C語言的記憶體佈局即可。
    而在C中,列舉申明其實就是按照數值進行一個個排序宣告。
    明顯的告訴你,std:: mem::transmute(1u8)解析以後得到的是Enum::Second

  • match
    我們可以使用確切的一些模式去匹配值,也可以忽略一個值_
    但是我們需要這麼一個不需要任何匹配卻需要獲取它的值的時候呢。

    match XXX {
      pat1 => {},
      pat2 => {},
      v => {}
    }

    很簡單,只需要一個簡單的名稱,就能夠標識:_匹配,並且獲取值。

  • namespace
    path就不斷提示,我們又相對路徑和絕對路徑。
    早就聽說過prelude,我們使用use的時候也有全路徑或者部分路徑的匯入。
    這些都來源於一個問題:namespace
    我們需要足夠的資訊去判斷某一個函式或物件,變數或常量的具體位置,具體值。
    當然,這是為了避免衝突。
    但是在某些即使不匯入也不衝突的地方,它的作用就是準確的定義這個值本身。

  • enum
    rust中,enum不只是常量列舉這麼簡單

    • 常量:簡單列舉
    • 結構:不同列舉可以定義不同的攜帶結構
    • 協議:impl相同的動作,不同的內容
    • 方法集:定義在列舉中還是定義在列舉攜帶的結構中,總能為我們引入方法

很簡單,既然傳入的是Enum::Second,我們這裡主要是執行match
不過遺憾的一個點,也是需要明確的一點是:即使在列舉內部,資料並不共享。
也就是說,即使是在Enum內部,也不能直接使用FirstSecond

java中,同一個class內,呼叫方法可以有兩種方式

  • method
  • this.method

當然,this關鍵字是可以省略的,但是,rust中的self是不能省略的。
失去了self的限定,就找不到該方法。
除非你是在當前的域中定義的一個方法,才能直接呼叫。

因此,這裡出現的FirstSecond並非列舉,無法進行匹配。
它標識的含義是wildcard全匹配,Second是永遠無法到達的痛。

如果想要明確FirstSecond,可以有三個方法

  • 全路徑申明:Enum::FirstEnum::Second
  • 自環境引用:Self::FirstSelf::Second
  • 環境匯入:use Enum::{First, Second}

First全匹配,結果自然是1

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章