Rust tidak memiliki dukungan asli untuk OOP tetapi Anda tetap dapat menggunakan teknik ini untuk memanfaatkan paradigma.
Pemrograman Berorientasi Objek (OOP) menyederhanakan desain perangkat lunak dengan menekankan penggunaan objek untuk mewakili entitas dan konsep dunia nyata. OOP mendorong pemeliharaan dengan mengenkapsulasi fungsionalitas dalam objek.
Rust adalah bahasa fleksibel yang mendukung pemrograman fungsional dan prosedural. Meskipun tidak mendukung pemrograman berorientasi objek secara asli, Anda dapat mengimplementasikan konsep OOP menggunakan tipe data bawaan Rust.
Enkapsulasi dalam Karat
Enkapsulasi memerlukan pengorganisasian kode ke dalam unit mandiri yang menyembunyikan detail internal sementara mengekspos antarmuka publik untuk interaksi eksternal untuk meminimalkan kompleksitas dan meningkatkan kode pemeliharaan.
Anda dapat mengenkapsulasi kode Rust dengan modul. Modul adalah kumpulan item termasuk fungsi, struct, enum, dan konstanta. Modul Rust menyediakan fungsionalitas untuk mengelompokkan dan menentukan batasan antara bagian-bagian dari suatu program.
Menggunakan Modul untuk Mengenkapsulasi Data dan Fungsi
Anda dapat menentukan modul menggunakan mod kata kunci diikuti dengan nama:
mod modul_saya {
// item modul buka di sini
}
Anda dapat mengatur modul secara hierarki dengan menyarangkan deklarasinya:
mod modul_induk {
mod modul_saya {
// item modul buka di sini
}
}
Anda kemudian dapat merujuk ke modul bersarang dengan hierarki penuh, memisahkan setiap modul dengan titik dua ganda, misalnya, parent_module:: my_module.
Secara default, item dalam modul bersifat pribadi dan hanya dapat diakses oleh kode dalam modul yang sama. Tapi Anda bisa membuat modul menjadi publik menggunakan pub kata kunci:
mod modul_saya {
pubfnmy_function() {
// badan fungsi ada di sini
}
}
Anda kemudian dapat mengakses my_function dari bagian lain dari program Anda.
Menggunakan Sifat untuk Mendefinisikan Perilaku
Cara lain Rust mengaktifkan enkapsulasi adalah melalui penggunaan sifat. Ciri menentukan perilaku yang dapat diimplementasikan oleh tipe dan memastikan bahwa tipe yang berbeda sesuai dengan antarmuka yang sama.
pubsifatDapat dicetak {
fnmencetak(&diri sendiri);
}pubstructTipe ku {
// struct bidang di sini
}
impl Dapat dicetak untuk Tipe ku {
fnmencetak(&diri sendiri) {
// implementasi di sini
}
}
Itu Dapat dicetak sifat memiliki a mencetak metode, dan Tipe ku struct mengimplementasikan Dapat dicetak sifat dengan menerapkan mencetak metode.
Dengan menggunakan ciri-ciri, Anda dapat memastikan bahwa jenis apa pun yang mengimplementasikan Dapat dicetak sifat memiliki a mencetak metode. Ini berguna saat bekerja dengan kode generik yang perlu beroperasi dengan tipe berbeda yang berbagi perilaku umum.
Warisan dalam Karat
Warisan memungkinkan Anda menentukan satu kelas berdasarkan kelas yang berbeda. Sub-kelas akan mewarisi properti dan metode dari induknya.
Di Rust, Anda didorong untuk menggunakan komposisi alih-alih warisan. Komposisi adalah proses menciptakan objek baru dengan menggabungkan yang sudah ada. Alih-alih membuat kelas baru yang mewarisi fungsionalitas dari kelas dasar, Anda dapat membuat struct baru yang berisi turunan dari struct dasar dan bidangnya.
Membuat Tipe Baru dengan Menggabungkan Tipe yang Sudah Ada
Anda akan menggunakan enum dan struct untuk membuat tipe baru. Enum berguna untuk tipe dengan nilai terbatas, dan struct dapat menampung banyak bidang.
Anda dapat membuat tipe enum untuk berbagai jenis hewan.
enumSatwa {
Kucing,
Anjing,
Burung,
// ...
}
Alternatifnya, Anda dapat membuat struct yang berisi bidang untuk setiap jenis hewan. Struct dapat menampung enum dan jenis lainnya.
structSatwa {
nama: Rangkaian,
usia: u8,
animal_type: Jenis Hewan,
}
enumJenis Hewan {
Kucing,
Anjing,
Burung,
// ...
}
Itu Satwa struct memegang nilai-nilai dari Jenis Hewan jenis enumerasi.
Anda dapat menggunakan sifat untuk menerapkan pewarisan dan menambahkan perilaku ke suatu tipe tanpa membuat yang baru.
sifatTerbang {
fnterbang(&diri sendiri);
}
Inilah cara Anda dapat mengimplementasikan Terbang sifat untuk beberapa jenis.
structBurung {
nama: Rangkaian,
lebar sayap: f32,
}impl Terbang untuk Burung {
fnterbang(&diri sendiri) {
cetak!("{} terbang!", diri sendiri.nama);
}
}structPesawat {
model: Rangkaian,
kecepatan maksimum: u32,
}
impl Terbang untuk Pesawat {
fnterbang(&diri sendiri) {
cetak!("{} terbang!", diri sendiri.model);
}
}
Itu Burung Dan Pesawat struct mengimplementasikan Terbang sifat dan cetak string dengan Cetak! makro.
Anda dapat menghubungi terbang metode pada kedua struct tanpa mengetahui tipe spesifiknya.
fnutama() {
membiarkan burung = Burung {
nama: Rangkaian::dari("Burung rajawali"),
lebar sayap: 2.0,
};membiarkan pesawat = Pesawat {
model: Rangkaian::dari("Boeing 747"),
kecepatan maksimum: 900,
};membiarkan objek_terbang: Vecdin Terbang> = vec![&burung, &pesawat];
untuk obyek di dalam objek_terbang {
objek.fly();
}
}
Itu utama fungsi instantiates Pesawat Dan Burung jenis. Itu benda_terbang vektor adalah vektor dari contoh objek, dan untuk loop melintasi vektor dan memanggil terbang metode pada contoh.
Menerapkan Polimorfisme di Rust
Kelas atau tipe adalah polimorfik jika beberapa jenis mewakili antarmuka. Karena sifat menyediakan fungsionalitas untuk menentukan perilaku di Rust, sambil menyediakan antarmuka umum untuk menulis kode generik, Anda dapat menggunakan Sifat untuk mengimplementasikan polimorfisme.
Inilah sifat bernama Dapat digambar yang mendefinisikan perilaku untuk merender objek di layar:
sifatDapat digambar {
fnmenggambar(&diri sendiri);
}
Tipe yang mengimplementasikan sifat Drawable dapat mengakses menggambar fungsi.
structPersegi panjang {
lebar: u32,
tinggi: u32,
}
impl Dapat digambar untuk Persegi panjang {
fnmenggambar(&diri sendiri) {
// Render persegi panjang di layar
}
}
Anda dapat menulis kode generik yang menggambar objek yang mengimplementasikan Dapat digambar sifat.
fndraw_object(objek: &T) {
objek.menggambar();
}
Itu draw_object fungsi mengambil tipe generik T
sebagai input yang mengimplementasikan Dapat digambar sifat dan memanggil menggambar metode pada sifat. Objek yang berbeda dapat mengimplementasikan Dapat digambar sifat dan mengakses fungsionalitas.
Menerapkan Abstraksi di Rust
Abstraksi adalah konsep OOP di mana kelas dan antarmuka dapat diakses oleh objek dan tipe tertentu. Anda dapat mengimplementasikan abstraksi di Rust dengan ciri-ciri.
Berikut adalah contoh sifat untuk pemutar media:
sifatMedia {
fnbermain(&diri sendiri);
}
Struktur dan enum yang mengimplementasikan Media sifat harus menyediakan implementasi untuk bermain metode.
structLagu {
judul: Rangkaian,
artis: Rangkaian,
}
impl Media untuk Lagu {
fnbermain(&diri sendiri) {
cetak!("Memutar lagu: {} oleh {}", diri sendiri.judul, diri sendiri.artis);
}
}
Itu Lagu struct mengimplementasikan Media sifat dengan menyediakan implementasi untuk bermain metode yang mencetak pesan dengan bidang Lagu struct ke konsol.
fnutama() {
// Buat instance dari struct Lagu
membiarkan lagu = lagu {
judul: Rangkaian::dari("Bohemian Rhapsody"),
artis: Rangkaian::dari("Ratu"),
};
// Panggil metode play pada instance lagu
lagu.bermain();
}
Itu lagu variabel adalah turunan dari Lagu struct, dan variabel dapat mengakses dan memanggil bermain metode.
Mengatur Kode Karat Itu Mudah
Pemrograman berorientasi objek membantu dengan organisasi kode. Berkat sistem modul Rust, Anda dapat dengan mudah mengatur kode Rust Anda sambil menerapkan konsep OOP untuk aplikasi Anda agar kode Anda tetap teratur, mudah dikelola, dan intuitif.