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 dengan Vec::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.