References and the dot operator
Kita telah mempelajari bahwa di saat kita memiliki sebuah reference, Anda perlu menggunakan *
untuk mendapatkan valuenya. Sebuah reference adalah type yang berbeda dari variabel aslinya, sehingga hal yang dicontohkan seperti hal di bawah ini tidak akan berjalan:
fn main() { let my_number = 9; let reference = &my_number; println!("{}", my_number == reference); // ⚠️ }
Dan compiler akan menyampaikan pesan berikut:
error[E0277]: can't compare `{integer}` with `&{integer}`
--> src\main.rs:5:30
|
5 | println!("{}", my_number == reference);
| ^^ no implementation for `{integer} == &{integer}`
Sehingga kita mengganti line 5 menjadi println!("{}", my_number == *reference);
dan sekarang outputnya adalah true
karena kondisinya sekarang adalah i32
== i32
, bukan i32
== &i32
. Hal seperti ini biasa disebut sebagai dereferencing.
Namun di saat Anda menggunakan method, Rust akan melakukan dereference secara otomatis. Tanda .
pada method biasa disebut sebagai dot operator, dan ia akan langsung melakukan dereferencing.
Pertama, kita buat sebuah struct dengan 1 field bertype u8
. Kemudian kita akan membuat sebuah reference ke field yang berada di dalam struct tersebut, dan mencoba untuk meng-comparenya (membandingkannya/mengkomparasinya). Dari contoh yang sebelumnya, bisa prediksikan bahwa hasilnya akan gagal :
struct Item { number: u8, } fn main() { let item = Item { number: 8, }; let reference_number = &item.number; // type dari reference_number adalah &u8 println!("{}", reference_number == 8); // ⚠️ &u8 dan u8 tidak bisa dikomparasi }
Untuk membuatnya bekerja, kita perlu untuk melakukan dereference: println!("{}", *reference_number == 8);
.
Namun dengan menggunakan dot operator, kita tidak lagi perlu untuk menggunakan *
. Contohnya:
struct Item { number: u8, } fn main() { let item = Item { number: 8, }; let reference_item = &item; println!("{}", reference_item.number == 8); // kita tidak perlu untuk menuliskan *reference_item.number }
Sekarang kita akan membuat sebuah method untuk Item
yang membandingkan number
dengan angka lainnya. Kita sama sekali tidak memerlukan *
dimanapun:
struct Item { number: u8, } impl Item { fn compare_number(&self, other_number: u8) { // ambil reference dari self println!("Are {} and {} equal? {}", self.number, other_number, self.number == other_number); // Kita tidak perlu lagi menuliskan *self.number } } fn main() { let item = Item { number: 8, }; let reference_item = &item; // ini bertype &Item let reference_item_two = &reference_item; // ini bertype &&Item item.compare_number(8); // method ini bisa berjalan reference_item.compare_number(8); // method yang ini juga berjalan reference_item_two.compare_number(8); // dan begitu pula pada bagian ini }
Jadi, cukup ingat hal ini: di saat Anda menggunakn .
(dot operator), Anda tidak lagi perlu mengkhawatirkan tentang *
.