Implementing structs and enums
Ini adalah dimana kita bisa mulai untuk memberikan kekuatan kepada structs dan enums. Untuk memanggil fungsi pada struct
atau enum
, kita bisa menggunakan block impl
. Fungsi ini biasanya disebut sebagai methods. Ada 2 macam method di dalam block impl
.
- Methods: ia menggunakan self (atau &self atau juga &mut self). Regular methods menggunakan
.
(period/titik)..clone()
adalah contoh dari sebuah regular method. - Associated functions (atau biasa dikenal sebagai "static" methods di beberapa bahasa pemrograman yang lain): ia tidak menggunakan self. Associated berarti "berhubungan dengan". Ia ditulis dengan cara yang berbeda, yaitu menggunakan
::
.String::from()
adalah contoh dari associated function, dan begitu juga denganVec::new()
. Anda biasanya akan sering melihat associated functions digunakan untuk membuat variabel baru.
Pada contoh yang kita gunakan ini kita akan membuat impl Animal dan membuat hasil printnya.
Untuk struct
atau enum
yang baru dibuat, Anda perlu memberikannya Debug jika Anda ingin menggunakan {:?}
untuk mencetaknya. Jika kita menuliskan #[derive(Debug)]
pada line sebelum ditulisnya struct atau enum, maka kita bisa mencetaknya dengan {:?}
. Pesan yang ditulis dengan #[]
disebut sebagai attributes. Kita terkadang bisa menggunakannya untuk memberitahukan compiler untuk memberikan kemampuan kepada struct agar bisa menggunakan Debug
. Ada banyak sekali attribute dan kita akan mempelajarinya kemudian. Tapi, derive
mungkin adalah attribute yang paling umum dan biasa Anda lihat pada bagian sebelum struct dan enum dideklarasikan.
#[derive(Debug)] struct Animal { age: u8, animal_type: AnimalType, } #[derive(Debug)] enum AnimalType { Cat, Dog, } impl Animal { fn new() -> Self { // Self ini adalah Animal. // Kita juga bisa menulisnya Animal bila kita tidak ingin menulisnya sebagai Self Self { // Saat kita menulis Animal::new(), kita akan selalu mendapatkan Kucing yang berusia 10 tahun age: 10, animal_type: AnimalType::Cat, } } fn change_to_dog(&mut self) { // Karena kita berada pada scope Animal, maka &mut self artinya adalah &mut Animal // gunakan .change_to_dog() untuk mengubah animal_typenya dari kucing, menjadi anjing // dengan menggunakan &mut self, kita bisa mengubahnya println!("Changing animal to dog!"); self.animal_type = AnimalType::Dog; } fn change_to_cat(&mut self) { // gunakan .change_to_cat() untuk mengubahnya dari anjing, menjadi kucing // dengan menggunakan &mut self, kita bisa mengubahnya println!("Changing animal to cat!"); self.animal_type = AnimalType::Cat; } fn check_type(&self) { // kita ingin membaca isi dari 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(); // Associated function untuk membuat animal yang baru // Secara default, ia adalah kucing yang berusia 10 tahun new_animal.check_type(); new_animal.change_to_dog(); new_animal.check_type(); new_animal.change_to_cat(); new_animal.check_type(); }
This prints:
The animal is a cat
Changing animal to dog!
The animal is a dog
Changing animal to cat!
The animal is a cat
Perlu diingat, bahwa Self (type Self) dan self (variabel self) merupakan abreviasi. (abreviasi = singkatan / cara terpendek untuk menulis sesuatu)
Jadi, pada code kita, Self = Animal. Juga, fn change_to_dog(&mut self)
berarti fn change_to_dog(&mut Animal)
.
Ini adalah satu contoh tambahan. Untuk contoh yang ini, kita akan menggunakan impl
pada enum
:
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(); }
Hasil cetaknya adalah Need sleep NOW
.