Mengiterasi Objek Trait
Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Rust di Coddy. Pelajaran 47 dari 61.
Sekarang kamu dapat menyimpan berbagai tipe dalam Vec<Box<dyn Trait>>, langkah berikutnya adalah memproses koleksi tersebut. Melakukan iterasi pada trait object sama seperti melakukan iterasi pada vector apa pun. Kamu menelusuri setiap elemen dan memanggil method yang didefinisikan oleh trait.
trait Shape {
fn area(&self) -> f64;
}
struct Circle { radius: f64 }
struct Rectangle { width: f64, height: f64 }
impl Shape for Circle {
fn area(&self) -> f64 { 3.14159 * self.radius * self.radius }
}
impl Shape for Rectangle {
fn area(&self) -> f64 { self.width * self.height }
}
fn main() {
let shapes: Vec<Box<dyn Shape>> = vec![
Box::new(Circle { radius: 2.0 }),
Box::new(Rectangle { width: 3.0, height: 4.0 }),
Box::new(Circle { radius: 1.0 }),
];
for shape in &shapes {
println!("Area: {}", shape.area());
}
}
Saat kamu melakukan iterasi dengan for shape in &shapes, setiap shape adalah referensi ke Box<dyn Shape>. Kamu bisa langsung memanggil method apa pun dari trait Shape: Rust menangani dispatch dinamis secara otomatis dengan memanggil implementasi yang tepat untuk setiap tipe konkret.
Pola ini sangat berguna untuk menggabungkan hasil. Kamu dapat menjumlahkan semua luas, memfilter bentuk berdasarkan ukuran, atau mengubah koleksi. Hal penting yang perlu dipahami adalah bahwa setelah item berada dalam koleksi trait object, kamu berinteraksi dengannya hanya melalui antarmuka trait, apa pun tipe dasarnya.
Tantangan
MudahMari kita buat kalkulator harga untuk keranjang belanja yang dapat menampung berbagai jenis barang! Kamu akan membuat sistem tempat produk dan layanan, masing-masing dengan logika harga yang berbeda, dapat disimpan bersama dan diproses untuk menghitung total harga.
Kamu akan mengatur kodemu dalam dua file:
items.rs: Definisikan trait publikPriceabledengan methodpriceyang menerima&selfdan mengembalikanf64. Lalu, buat dua struct publik:Product: dengan field publikname(String) dancost(f64). Methodprice-nya cukup mengembalikancost.Service: dengan field publikname(String),hourly_rate(f64), danhours(f64). Methodprice-nya harus mengembalikanhourly_rate * hours.
main.rs: Gunakan module items-mu dan buat vector bertipeVec<Box<dyn Priceable>>. Gunakan input untuk membuat satu Product dan satu Service, tambahkan keduanya ke vector-mu, lalu lakukan iterasi pada koleksi tersebut untuk menghitung dan mencetak total harga semua barang.
Keunggulan trait object terlihat di sini. Kodemu untuk melakukan iterasi tidak perlu mengetahui apakah yang sedang diproses adalah Product atau Service. Kode tersebut cukup memanggil price() pada setiap barang, lalu Rust secara otomatis memanggil implementasi yang tepat.
Output-mu harus menampilkan total harga dengan dua angka di belakang koma:
Total: ${total}Contohnya, dengan input Laptop, 999.99, Consulting, 150.0, dan 3.0:
Total: $1449.99Dan dengan input Book, 29.99, Tutoring, 50.0, dan 2.0:
Total: $129.99Kamu akan menerima lima input: nama produk, biaya produk, nama layanan, tarif per jam, dan jumlah jam kerja (parse nilai numerik sebagai f64).
Coba sendiri
mod items;
use items::{Priceable, Product, Service};
fn main() {
// Baca input
let mut product_name = String::new();
std::io::stdin().read_line(&mut product_name).expect("Failed to read line");
let product_name = product_name.trim().to_string();
let mut product_cost = String::new();
std::io::stdin().read_line(&mut product_cost).expect("Failed to read line");
let product_cost: f64 = product_cost.trim().parse().expect("Failed to parse");
let mut service_name = String::new();
std::io::stdin().read_line(&mut service_name).expect("Failed to read line");
let service_name = service_name.trim().to_string();
let mut hourly_rate = String::new();
std::io::stdin().read_line(&mut hourly_rate).expect("Failed to read line");
let hourly_rate: f64 = hourly_rate.trim().parse().expect("Failed to parse");
let mut hours = String::new();
std::io::stdin().read_line(&mut hours).expect("Failed to read line");
let hours: f64 = hours.trim().parse().expect("Failed to parse");
// TODO: Buat Product menggunakan product_name dan product_cost
// TODO: Buat Service menggunakan service_name, hourly_rate, dan hours
// TODO: Buat Vec<Box<dyn Priceable>> dan tambahkan kedua item ke dalamnya
// TODO: Telusuri vektor dan hitung harga totalnya
// TODO: Cetak totalnya dengan satu angka di belakang koma
// Format: Total: ${total:.1}
}
Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.
Semua pelajaran di Pemrograman Berorientasi Objek
1Method dan Perilaku
Pengantar Blok ImplementasiParameter SelfMethod MutableFungsi TerkaitBeberapa Blok ImplementasiMethod BerantaiRangkuman: Aksi Persegi Panjang4Proyek: Hewan Peliharaan Virtual
Mendefinisikan Hewan PeliharaanMemberi Makan Hewan Peliharaan2Enkapsulasi dan module
Dasar-Dasar moduleKata Kunci publicField privateGetterSetterRekap: Loker AmanLatihan sendiri: Compiler Rust online