Trait Nesneleri Üzerinde Yineleme
Coddy'nin Rust Journey'sinin Nesne Yönelimli Programlama 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, sonraki adım bu koleksiyonu işlemektir. Trait nesneleri üzerinde yineleme yapmak, herhangi bir vektör üzerinde yineleme yapmakla tamamen aynıdı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 yineleme yaptığında, her shape bir Box<dyn Shape> başvurusudur. Shape trait'inin herhangi bir metodunu doğrudan çağırabilirsin: Rust, dinamik gönderimi otomatik olarak yönetir ve her somut tür için doğru uygulamayı çağırır.
Bu kalıp, sonuçları toplamak için güçlüdür. Tüm alanları toplayabilir, şekilleri boyuta göre filtreleyebilir veya koleksiyonu dönüştürebilirsiniz. Temel fikir şudur: Öğeler bir trait nesnesi koleksiyonuna girdikten sonra, temel türleri ne olursa olsun onlarla yalnızca trait’in arayüzü üzerinden etkileşim kurarsınız.
Görev
KolayFarklı türlerde öğeler barındırabilen bir alışveriş sepeti için fiyat hesaplayıcı oluşturalım! Her biri farklı fiyatlandırma mantığına sahip ürün ve hizmetlerin birlikte depolanıp toplam fiyatı hesaplamak üzere işleneceği bir sistem oluşturacaksın.
Kodunu iki dosyaya ayıracaksın:
items.rs:&selfalan vef64döndüren birpriceyöntemine sahip herkese açık birPriceabletrait'i tanımla. Ardından iki herkese açık struct oluştur:Product: herkese açıkname(String) vecost(f64) alanlarına sahip olsun.pricedeğeri doğrudancostdeğerini döndürmelidir.Service: herkese açıkname(String),hourly_rate(f64) vehours(f64) alanlarına sahip olsun.pricedeğerihourly_rate * hoursdöndürmelidir.
main.rs: items modülünü dahil et veVec<Box<dyn Priceable>>türünde bir vektör oluştur. Girdileri kullanarak bir Product ve bir Service oluştur, bunları vektörüne ekle, ardından toplam fiyatı hesaplamak ve tüm öğelerin toplam fiyatını yazdırmak için koleksiyon üzerinde yinele.
Trait nesnelerinin gücü burada ortaya çıkar. Yineleme kodunun bir Product mı yoksa Service mi işlediğini bilmesi gerekmez. Her öğe üzerinde yalnızca price() çağrısı yapar ve Rust otomatik olarak doğru uygulamaya yönlendirme yapar.
Çıktın toplam fiyatı iki ondalık basamakla göstermelidir:
Total: ${total}Örneğin, Laptop, 999.99, Consulting, 150.0 ve 3.0 girdileriyle:
Total: $1449.99Ve Book, 29.99, Tutoring, 50.0 ve 2.0 girdileriyle:
Total: $129.99Beş girdi alacaksın: ürün adı, ürün maliyeti, hizmet adı, saatlik ücret ve çalışılan saatler (sayısal değerleri f64 olarak ayrıştır).
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");
// TODO: product_name ve product_cost kullanarak bir Product oluştur
// TODO: service_name, hourly_rate ve hours kullanarak bir Service oluştur
// TODO: Bir Vec<Box<dyn Priceable>> oluştur ve her iki öğeyi de ona ekle
// TODO: Vektör üzerinde döngü yap ve toplam fiyatı hesapla
// TODO: Toplamı bir ondalık basamakla yazdır
// Biçim: Total: ${total:.1}
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1Metotlar ve Davranış
Uygulama Bloklarına GirişSelf ParametresiDeğiştirilebilir Metotlarİlişkili FonksiyonlarBirden Fazla Uygulama BloğuMetot ZincirlemeÖzet - Dikdörtgen Eylemleri4Proje: Sanal Evcil Hayvan
Evcil Hayvanı TanımlamaEvcil Hayvanı Besleme2Kapsülleme ve Modüller
Modül TemelleriPublic Anahtar KelimesiPrivate AlanlarGetter'larSetter'larÖzet - Güvenli Kasa5Generic Yapılar
Generic Struct'larGeneric MetotlarÇoklu Generic TürlerGeneric FonksiyonlarÖzet - Koordinat Noktası8Sınırlandırıcı Olarak Trait'ler
Trait Sınırlandırıcı SözdizimiÇoklu SınırlandırıcılarWhere CümleciğiTrait'ler ile Tip DöndürmeÖzet - Generic Yazıcı11Rust'ta Tasarım Kalıpları
Newtype KalıbıKompozisyonDrop Trait'iFrom ve IntoÖzet - Smart Pointer Mock3İleri Seviye Enum'lar
Veri İçeren Enum'larEnum MetotlarıVeri Varyantlarını EşlemeOption Enum'ına Yeniden BakışÖzet - Shape Enum6Trait Tanımlama
Trait Nedir?Traitleri UygulamaVarsayılan UygulamalarVarsayılanları Geçersiz KılmaParametreli TraitlerÖzet - Media Player9Trait Nesneleri
Dinamik GönderimTrait VektörleriTrait Nesneleri Üzerinde YinelemeÖzet - Hayvanat Bahçesi YöneticisiKendi başına pratik yap: Online Rust derleyicisi