實作結構體和列舉
從這裡開始你可以給予你的結構體和列舉一些真正的威力。要對 struct
或 enum
呼叫的函式,要寫在 impl
區塊。這些函式被稱為方法(method)。impl
區塊中的方法有兩類。
- 方法:這些方法會取用 self(或是 &self 或 &mut self)。正規方法使用"."(英文句號)。
.clone()
是一個正規方法的例子。 - 關聯函式(associated function, 在某些語言中被稱為"靜態(static)"方法):這些函式不使用 self。關聯的意思是"有相關的"。它們的書寫方式不同,用的是
::
。String::from()
是一個關聯函式,Vec::new()
也是。你看到的關聯函式最常被用來建立新變數。
我們將在我們的範例中建立 Animal 並印出它們。
對於新的 struct
或 enum
,如果你想使用 {:?}
印出來,你需要給它Debug,我們也將會這樣做。如果你在結構體或列舉上面寫了 #[derive(Debug)]
,那麼你就可以用 {:?}
印出來。這些帶有 #[]
的訊息被稱為屬性(attributes)。你有時可以用它們來告訴編譯器給你的結構體像是 Debug
的能力。屬性有很多種,我們以後會學到。但是 derive
可能是最常見的,你經常在結構體和列舉上面看到它。
#[derive(Debug)] struct Animal { age: u8, animal_type: AnimalType, } #[derive(Debug)] enum AnimalType { Cat, Dog, } impl Animal { fn new() -> Self { // Self 指的是 Animal。 // 你也可以寫 Animal 而非 Self Self { // 當我們寫 Animal::new() 我們永遠會得到10歲的貓 age: 10, animal_type: AnimalType::Cat, } } fn change_to_dog(&mut self) { // 因為我們在Animal裡, &mut self 指的是 &mut Animal // 用 .change_to_dog() 把貓改成狗 // 有了 &mut self 我們就能更改 println!("Changing animal to dog!"); self.animal_type = AnimalType::Dog; } fn change_to_cat(&mut self) { // 用 .change_to_cat() 把狗改成貓 // 有了 &mut self 我們就能更改 println!("Changing animal to cat!"); self.animal_type = AnimalType::Cat; } fn check_type(&self) { // we want to read self match self.animal_type { AnimalType::Dog => println!("The animal is a dog"), AnimalType::Cat => println!("The animal is a cat"), } } } fn main() { let mut new_animal = Animal::new(); // 用關聯函式建立新動物 // 它是一隻10歲的貓 new_animal.check_type(); new_animal.change_to_dog(); new_animal.check_type(); new_animal.change_to_cat(); new_animal.check_type(); }
印出:
The animal is a cat
Changing animal to dog!
The animal is a dog
Changing animal to cat!
The animal is a cat
記住,Self(型別 Self)和 self(變數 self)是縮寫。(縮寫 = 簡寫方式)
所以在我們的程式碼中,Self = Animal。另外,fn change_to_dog(&mut self)
的意思是 fn change_to_dog(&mut Animal)
。
下面再舉一個小例子。這次我們將在 enum
上使用 impl
:
enum Mood { Good, Bad, Sleepy, } impl Mood { fn check(&self) { match self { Mood::Good => println!("Feeling good!"), Mood::Bad => println!("Eh, not feeling so good"), Mood::Sleepy => println!("Need sleep NOW"), } } } fn main() { let my_mood = Mood::Sleepy; my_mood.check(); }
印出 Need sleep NOW
。