מעבר על אובייקטים של Trait
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Rust של Coddy. שיעור 47 מתוך 61.
עכשיו, כשאפשר לאחסן סוגים שונים ב־Vec<Box<dyn Trait>>, השלב הבא הוא לעבד את האוסף הזה. איטרציה על אובייקטים של trait פועלת בדיוק כמו איטרציה על כל וקטור אחר. עוברים בלולאה על כל איבר וקוראים למתודות שהוגדרו ב־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());
}
}
כשאתם מבצעים איטרציה באמצעות for shape in &shapes, כל shape הוא הפניה אל Box<dyn Shape>. אפשר לקרוא ישירות לכל מתודה מתוך ה-trait Shape: Rust מטפלת בשיגור הדינמי באופן אוטומטי וקוראת למימוש הנכון עבור כל טיפוס קונקרטי.
התבנית הזאת יעילה לצבירת תוצאות. אפשר לסכום את כל השטחים, לסנן צורות לפי גודל או לשנות את האוסף. התובנה המרכזית היא שברגע שהפריטים נמצאים באוסף של אובייקטי תכונה, מתקשרים איתם אך ורק דרך הממשק של התכונה, ללא קשר לסוגים הבסיסיים שלהם.
אתגר
קלנבנה מחשבון מחירים לעגלת קניות שיכולה להכיל סוגים שונים של פריטים! תיצור מערכת שבה אפשר לאחסן יחד מוצרים ושירותים, שלכל אחד מהם לוגיקת תמחור שונה, ולעבד אותם כדי לחשב את המחיר הכולל.
תארגן את הקוד שלך בשני קבצים:
items.rs: תגדיר trait ציבורי בשםPriceableעם מתודה בשםpriceשמקבלת את&selfומחזירהf64. לאחר מכן, תיצור שני מבנים ציבוריים:Product: עם שדות ציבורייםname(String) ו-cost(f64). המתודהpriceשלו צריכה פשוט להחזיר אתcost.Service: עם השדות הציבורייםname(String),hourly_rate(f64) ו-hours(f64). המתודהpriceשלו צריכה להחזיר אתhourly_rate * hours.
main.rs: תכלול את מודול הפריטים שלך ותיצור וקטור מסוגVec<Box<dyn Priceable>>. השתמש בקלטים כדי ליצור Product אחד ו-Service אחד, הוסף אותם לווקטור שלך, ואז עבור על האוסף כדי לחשב ולהדפיס את המחיר הכולל של כל הפריטים.
העוצמה של אובייקטי trait באה כאן לידי ביטוי. קוד המעבר שלך לא צריך לדעת אם הוא מעבד Product או Service. הוא פשוט קורא ל-price() עבור כל פריט, ו-Rust מנתב באופן אוטומטי למימוש הנכון.
הפלט שלך צריך להציג את המחיר הכולל עם שתי ספרות אחרי הנקודה העשרונית:
Total: ${total}לדוגמה, עבור הקלטים Laptop, 999.99, Consulting, 150.0 ו-3.0:
Total: $1449.99ועבור הקלטים Book, 29.99, Tutoring, 50.0 ו-2.0:
Total: $129.99תקבל חמישה קלטים: שם המוצר, עלות המוצר, שם השירות, התעריף לשעה ומספר שעות העבודה (יש לנתח את הערכים המספריים בתור f64).
נסו בעצמכם
mod items;
use items::{Priceable, Product, Service};
fn main() {
// קרא את הקלטים
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 באמצעות product_name ו-product_cost
// TODO: צור Service באמצעות service_name, hourly_rate ו-hours
// TODO: צור Vec<Box<dyn Priceable>> והוסף אליו את שני הפריטים
// TODO: עבור על הווקטור וחשב את המחיר הכולל
// TODO: הדפס את הסכום הכולל עם ספרה אחת אחרי הנקודה העשרונית
// פורמט: Total: ${total:.1}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1מתודות והתנהגות
מבוא לבלוקי מימושהפרמטר selfמתודות ניתנות לשינויפונקציות משויכותבלוקי מימוש מרוביםשרשור מתודותסיכום – פעולות מלבן4פרויקט: חיית מחמד וירטואלית
הגדרת חיית המחמדהאכלת חיית המחמדתרגלו בעצמכם: קומפיילר Rust אונליין