Menu
Coddy logo textTech

Trait Nesneleri Üzerinde Yineleme

Coddy'nin Rust Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 47 / 61.

Artık farklı türleri bir Vec<Box<dyn Trait>> içinde saklayabildiğinize göre, bir sonraki adım bu koleksiyonu işlemektir. Trait nesneleri üzerinde yineleme yapmak, herhangi bir vektör üzerinde yineleme yapmakla aynı şekilde çalışır—her bir öğe üzerinde döngü kurar ve trait tarafından tanımlanan metotları çağırırsınız.

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());
    }
}

for shape in &shapes ile döngü kurduğunuzda, her bir shape bir Box<dyn Shape> referansıdır. Shape trait'inden herhangi bir metodu doğrudan çağırabilirsiniz; Rust dinamik sevki (dynamic dispatch) otomatik olarak yöneterek her somut tür için doğru uygulamayı çağırır.

Bu desen, sonuçları toplamak için güçlüdür. Tüm alanları toplayabilir, şekilleri boyutlarına göre filtreleyebilir veya koleksiyonu dönüştürebilirsiniz. Temel içgörü şudur: Öğeler bir trait nesnesi koleksiyonuna girdikten sonra, temel türlerinden bağımsız olarak onlarla tamamen trait'in arayüzü üzerinden etkileşime girersiniz.

challenge icon

Görev

Kolay

Farklı türde öğeleri tutabilen bir alışveriş sepeti için bir fiyat hesaplayıcı oluşturalım! Ürünlerin ve hizmetlerin—her biri farklı fiyatlandırma mantığına sahip—birlikte saklanabileceği ve toplam fiyatı hesaplamak için işlenebileceği bir sistem oluşturacaksınız.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • items.rs: &self alan ve bir f64 döndüren bir price metoduna sahip genel bir Priceable trait'i tanımlayın. Ardından iki genel struct oluşturun:
    • Product — genel name (String) ve cost (f64) alanlarına sahip. price metodu sadece cost değerini döndürmelidir.
    • Service — genel name (String), hourly_rate (f64) ve hours (f64) alanlarına sahip. price metodu hourly_rate * hours değerini döndürmelidir.
  • main.rs: items modülünüzü dahil edin ve Vec<Box<dyn Priceable>> türünde bir vektör oluşturun. Girdileri kullanarak bir Product ve bir Service oluşturun, bunları vektörünüze ekleyin, ardından tüm öğelerin toplam fiyatını hesaplamak ve yazdırmak için koleksiyon üzerinde döngü kurun.

Trait nesnelerinin gücü burada parlıyor—döngü kodunuzun bir Product mı yoksa bir Service mi işlediğini bilmesine gerek yoktur. Sadece her öğe üzerinde price() metodunu çağırır ve Rust otomatik olarak doğru uygulamaya yönlendirir.

Çıktınız toplam fiyatı bir ondalık basamakla göstermelidir:

Total: ${total}

Örneğin, Laptop, 999.99, Consulting, 150.0 ve 3.0 girdileriyle:

Total: $1449.99

Ve Book, 29.99, Tutoring, 50.0 ve 2.0 girdileriyle:

Total: $129.99

Beş girdi alacaksınız: ürün adı, ürün maliyeti, hizmet adı, saatlik ücret ve çalışılan saat (sayısal değerleri f64 olarak ayrıştırın).

Kopya kağıdı

Bir trait nesneleri koleksiyonu üzerinde yineleme yapmak için, vektöre bir referansla birlikte standart bir for döngüsü kullanın:

for item in &collection {
    item.trait_method();
}

for item in &vec ile yineleme yaparken, her bir item bir Box<dyn Trait> referansıdır. Trait içindeki herhangi bir metodu doğrudan çağırabilirsiniz; Rust, dinamik sevki (dynamic dispatch) otomatik olarak yönetir ve her somut tür için doğru uygulamayı çağırır.

Sonuçları bir araya getirmek için trait nesneleri üzerinde yineleme örneği:

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 }),
    ];

    for shape in &shapes {
        println!("Area: {}", shape.area());
    }
}

Bu desen, sonuçları bir araya getirmek için kullanışlıdır; değerleri toplayabilir, kriterlere göre filtreleyebilir veya öğelerle tamamen trait arayüzü üzerinden etkileşime girerken koleksiyonu dönüştürebilirsiniz.

Kendin dene

mod items;

use items::{Priceable, Product, Service};

fn main() {
    // Girdileri oku
    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");

    // YAPILACAK: product_name ve product_cost kullanarak bir Product oluşturun

    // YAPILACAK: service_name, hourly_rate ve hours kullanarak bir Service oluşturun

    // YAPILACAK: Bir Vec<Box<dyn Priceable>> oluşturun ve her iki öğeyi de buna ekleyin

    // YAPILACAK: Vektör üzerinde döngü kurun ve toplam fiyatı hesaplayın

    // YAPILACAK: Toplamı bir ondalık basamakla yazdırın
    // Format: Toplam: ${total:.1}
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Object Oriented Programming bölümündeki tüm dersler