Ini sekarang disinggung dalam edisi kedua The Rust Programming Language . Namun, mari selami sedikit sebagai tambahan.
Mari kita mulai dengan contoh yang lebih sederhana.
Kapan tepat menggunakan metode sifat?
Ada beberapa cara untuk memberikan penjilidan terlambat :
trait MyTrait {
fn hello_word(&self) -> String;
}
Atau:
struct MyTrait<T> {
t: T,
hello_world: fn(&T) -> String,
}
impl<T> MyTrait<T> {
fn new(t: T, hello_world: fn(&T) -> String) -> MyTrait<T>;
fn hello_world(&self) -> String {
(self.hello_world)(self.t)
}
}
Dengan mengabaikan strategi implementasi / kinerja apa pun, kedua kutipan di atas memungkinkan pengguna untuk menentukan secara dinamis bagaimana hello_worldseharusnya berperilaku.
Satu perbedaan (secara semantik) adalah bahwa traitimplementasi menjamin bahwa untuk tipe tertentu yang Tmengimplementasikan trait, hello_worldakan selalu memiliki perilaku yang sama sedangkan structimplementasi memungkinkan memiliki perilaku yang berbeda pada basis per contoh.
Apakah menggunakan metode itu tepat atau tidak tergantung pada kasus penggunaan!
Kapan waktu yang tepat untuk menggunakan tipe terkait?
Mirip dengan traitmetode di atas, tipe terkait adalah bentuk pengikatan akhir (meskipun terjadi saat kompilasi), yang memungkinkan pengguna traituntuk menentukan jenis yang akan diganti untuk instance tertentu. Ini bukan satu-satunya cara (jadi pertanyaannya):
trait MyTrait {
type Return;
fn hello_world(&self) -> Self::Return;
}
Atau:
trait MyTrait<Return> {
fn hello_world(&Self) -> Return;
}
Setara dengan metode pengikatan akhir di atas:
- yang pertama memaksakan bahwa untuk yang diberikan
Selfada satu yang Returnterkait
- yang kedua, sebaliknya, memungkinkan menerapkan
MyTraituntuk Selfuntuk beberapaReturn
Bentuk mana yang lebih tepat bergantung pada apakah masuk akal untuk menegakkan kesatuan atau tidak. Sebagai contoh:
Deref menggunakan tipe yang diasosiasikan karena tanpa unicity compiler akan menjadi gila selama inferensi
Add menggunakan tipe terkait karena pembuatnya berpikir bahwa dengan dua argumen akan ada tipe pengembalian logis
Seperti yang Anda lihat, meskipun Derefmerupakan kasus penggunaan yang jelas (kendala teknis), kasusnya Addkurang jelas: mungkin masuk akal untuk i32 + i32menghasilkan salah satu i32atau Complex<i32>bergantung pada konteksnya? Meskipun demikian, penulis menjalankan penilaian mereka dan memutuskan bahwa kelebihan jenis pengembalian untuk penambahan tidak diperlukan.
Pendapat pribadi saya adalah bahwa tidak ada jawaban yang benar. Namun, di luar argumen unicity, saya akan menyebutkan bahwa tipe terkait membuat penggunaan sifat lebih mudah karena mereka mengurangi jumlah parameter yang harus ditentukan, jadi jika manfaat dari fleksibilitas menggunakan parameter sifat biasa tidak jelas, saya menyarankan untuk memulai dengan jenis yang terkait.
trait/struct MyTrait/MyStructmemungkinkan tepat satuimpl MyTrait foratauimpl MyStruct.trait MyTrait<Return>memungkinkan beberapaimplkarena bersifat umum.Returnbisa tipe apapun. Struct generik sama.