Menu
CoddyTech

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.

challenge icon

Tantangan

Mudah

Mari 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 publik Priceable dengan method price yang menerima &self dan mengembalikan f64. Lalu, buat dua struct publik:
    • Product: dengan field publik name (String) dan cost (f64). Method price-nya cukup mengembalikan cost.
    • Service: dengan field publik name (String), hourly_rate (f64), dan hours (f64). Method price-nya harus mengembalikan hourly_rate * hours.
  • main.rs: Gunakan module items-mu dan buat vector bertipe Vec<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.99

Dan dengan input Book, 29.99, Tutoring, 50.0, dan 2.0:

Total: $129.99

Kamu 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}
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Rust online