Memahami Jenis Generik Karat
Table of content:
Selalu ada tingkat ketidakpastian saat mengembangkan aplikasi, yang dapat menyebabkan kesalahan, terutama jika fungsi Anda menerima jenis argumen tertentu. Untuk mengurangi error akibat ketidakpastian, Anda bisa menggunakan Generics. Generik menyediakan fungsionalitas untuk membuat kelas, fungsi, dan struktur data untuk bekerja dengan tipe yang berbeda.
Dengan menggunakan obat generik, Anda dapat membuat dan menentukan algoritme dan struktur data yang dapat beroperasi pada berbagai jenis tanpa menulis kode yang rumit dan memisahkan implementasi untuk setiap jenis. Generik meningkatkan penggunaan kembali kode dan efisiensi sambil mempertahankan keamanan dan kinerja jenis.
Menggunakan Jenis Generik di Rust
Tipe generik Rust dapat beroperasi dengan tipe data Rust lainnya. Anda akan menentukan tipe generik dengan kurung sudut (<>), diikuti oleh dua atau lebih parameter.
Inilah definisi struct generik yang mengambil dua parameter tipe generik:
struct Point<T, U> {
x: T,
y: U,
}
Dalam Titik struktur, T, Dan AS adalah parameter tipe generik.
Anda dapat mengganti parameter tipe generik dengan tipe data apa pun pada instantiasi:
fn main() {
let my_point = Point { x: String::from("hello"), y: String::from("world") }; println!(
"The x value of my_point is {} and the y value is {}.",
my_point.x,
my_point.y
);
}
Itu my_point variabel adalah turunan dari Titik struct diinisialisasi dengan tipe string. Kompiler Rust menyimpulkan jenis konkret dari T Dan AS berdasarkan nilai-nilai pada instantiation.
Batas Sifat untuk Tipe Generik
Jenis generik karat dapat menggunakan batas sifat untuk memastikan keamanan jenis. Ciri-ciri adalah kumpulan metode yang dapat diterapkan tipe untuk menunjukkan perilaku tertentu yang ditentukan untuk sifat tersebut.
Batasan sifat menentukan bahwa tipe generik harus mengimplementasikan satu atau beberapa sifat.
Berikut adalah contoh fungsi generik yang mengembalikan nilai yang lebih besar dari dua nilai dengan sifat terikat yang memastikan bahwa tipe yang dibandingkan mengimplementasikan sifat tersebut:
trait Maximum {
fn max(self, other: Self) -> Self;
}
impl<T: PartialOrd> Maximum for T {
fn max(self, other: Self) -> Self {
if self > other {
self
} else {
other
}
}
}
fn main() {
let a = 5;
let b = 10;
let largest = Maximum::max(a, b);
println!("The largest value is {}", largest);
}
Itu Maksimum sifat memiliki a maks metode yang mengembalikan yang lebih besar dari dua nilai dari jenis yang sama. Jenis apa pun yang mengimplementasikan PartialOrd sifat mengimplementasikan Maksimum sifat.
Itu maks metode mengambil dua nilai dari Diri sendiri type—mengacu pada tipe yang mengimplementasikan the Maksimum sifat-dan membandingkan nilai-nilai.
Itu utama fungsi membandingkan dua variabel menggunakan maks metode dan mencetak yang terbesar.
Batasan untuk Tipe Generik
Batasan mirip dengan batas sifat, tetapi batasan memungkinkan Anda untuk menentukan persyaratan tambahan pada tipe yang Anda gunakan sebagai parameter tipe.
Jika Anda ingin membuat fungsi generik yang menerima tipe untuk konversi string, Anda bisa menggunakan batasan untuk memastikan bahwa parameter tipe mengimplementasikan suatu sifat.
trait ToString {
fn to_string(&self) -> String;
}
fn to_string<T: ToString>(value: T) -> String {
value.to_string()
}
Itu to_string nilai parameter harus menerapkan ToString sifat, yang memastikan bahwa Anda dapat mengonversi nilai tipe T untuk string dengan to_string metode.
Tipe Generik Berguna untuk Bekerja Dengan Sifat
Jenis generik karat sangat kuat, dan ada area untuk perbaikan. Area fokus kritis adalah meningkatkan kinerja kode generik. Saat ini, sistem tipe Rust dapat memaksakan overhead pada kode generik, memperlambat kinerja.
Jenis generik bermanfaat untuk bekerja dengan sifat. Dengan menggunakan tipe generik, Anda dapat membuat objek sifat yang bekerja dengan tipe apa pun yang mengimplementasikan suatu sifat untuk membuat metode Anda lebih fleksibel.