Clone ו-Copy
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Rust של Coddy. שיעור 37 מתוך 61.
ב-Rust, כשמקצים ערך למשתנה אחר, הבעלות בדרך כלל עוברת: המשתנה המקורי נעשה לא תקף. עם זאת, שתי תכונות סטנדרטיות משנות את ההתנהגות הזאת: Clone ו-Copy.
המאפיין Copy מאפשר העתקה סיבית משתמעת. כאשר טיפוס מממש את Copy, השמתו למשתנה אחר יוצרת עותק אוטומטי במקום להעביר את הבעלות:
#[derive(Copy, Clone)]
struct Point {
x: i32,
y: i32,
}
let p1 = Point { x: 10, y: 20 };
let p2 = p1; // p1 מועתק, ולא מועבר
println!("{}, {}", p1.x, p2.x); // שניהם תקינים!
המאפיין Clone מספק העתקה עמוקה מפורשת באמצעות המתודה .clone(). הוא נדרש בכל פעם שגוזרים את Copy, אך אפשר להשתמש בו גם בפני עצמו עבור טיפוסים שזקוקים להעתקה מפורשת:
let p3 = p1.clone(); // העתקה מפורשת
יש מגבלה חשובה: ניתן לגזור את Copy רק עבור טיפוסים שכל השדות שלהם מממשים גם הם את Copy. טיפוסים פשוטים כמו מספרים שלמים ומספרים עשרוניים מממשים את Copy, אבל String לא. הוא מנהל זיכרון בערימה. אם המבנה שלך מכיל String, אפשר לגזור רק את Clone, ולא את Copy.
| מאפיין | התנהגות | שימוש |
|---|---|---|
Copy | מרומז, אוטומטי | נתונים פשוטים המאוחסנים במחסנית בלבד |
Clone | מפורש באמצעות .clone() | כל נתון שניתן לשכפל |
עבור מבנים פשוטים עם שדות פרימיטיביים, גזירה של שתי התכונות מאפשרת לך להקצות ערכים בחופשיות בלי לדאוג לבעלות.
אתגר
קלבואו נבנה מערכת צירים שמדגימה את ההבדל בין התכונות Copy ו-Clone! תיצרו שתי מבנים, אחד שאפשר להעתיק באופן משתמע ואחד שמחייב שכפול מפורש, כדי לראות כיצד Rust מטפלת בשכפול באופן שונה בהתאם לתכונות שגוזרים.
תארגנו את הקוד בשני קבצים:
coordinates.rs: הגדירו שני מבנים ציבוריים שמייצגים סוגים שונים של קואורדינטות:GridPoint: עם השדות הציבורייםxו-y(שניהם מסוגi32). מכיוון שהוא מכיל רק טיפוסים פרימיטיביים, גזרו גם אתCopyוגם אתClone, כך שאפשר יהיה להעתיק אותו באופן משתמע בעת השמה.NamedLocation: עםnameציבורי (String) ושדותx/y(i32). מכיוון שהוא מכילString, אפשר לגזור רק אתClone, ולא אתCopy. המבנה הזה יחייב קריאות מפורשות ל-.clone()כדי לשכפל אותו.
main.rs: כללו את מודול הקואורדינטות והדגימו כיצד כל מבנה מתנהג באופן שונה כשמשכפלים אותו. צרו מופעים באמצעות הקלטים שסופקו, ואז הראו ש:- אפשר להש assigned
GridPointלמשתנה אחר, ושניהם נשארים תקפים (העתקה משתמעת) - חובה להשתמש ב-
.clone()עבורNamedLocationכדי ליצור עותק, תוך שמירה על המקור כתקף
- אפשר להש assigned
הפלט שלכם צריך להציג את הערכים המקוריים ואת הערכים שהועתקו/שוכפלו, כדי להוכיח ששני המשתנים תקפים לאחר השכפול:
Original point: ({x}, {y})
Copied point: ({x}, {y})
Original location: {name} at ({x}, {y})
Cloned location: {name} at ({x}, {y})לדוגמה, עבור הקלטים 5, 10 ו-Home:
Original point: (5, 10)
Copied point: (5, 10)
Original location: Home at (5, 10)
Cloned location: Home at (5, 10)תקבלו שלושה קלטים: קואורדינטת x (יש לנתח כ-i32), קואורדינטת y (יש לנתח כ-i32) ושם המיקום.
נסו בעצמכם
mod coordinates;
use coordinates::{GridPoint, NamedLocation};
fn main() {
// קרא את הקלטים
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let x: i32 = input1.trim().parse().expect("Invalid number");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let y: i32 = input2.trim().parse().expect("Invalid number");
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let name = input3.trim().to_string();
// TODO: צור מופע של GridPoint עם x ו-y
// TODO: הדגם העתקה מרומזת באמצעות השמה למשתנה אחר
// (GridPoint מממש את Copy, ולכן נוצר עותק אוטומטית)
// TODO: הדפס את הנקודה המקורית ואת העותק שלה
// פורמט: "Original point: ({x}, {y})"
// פורמט: "Copied point: ({x}, {y})"
// TODO: צור מופע של NamedLocation עם name, x ו-y
// TODO: הדגם שכפול מפורש (NamedLocation מממש רק את Clone, ולא את Copy)
// השתמש ב-.clone() כדי ליצור עותק
// TODO: הדפס את המיקום המקורי ואת העותק המשוכפל שלו
// פורמט: "Original location: {name} at ({x}, {y})"
// פורמט: "Cloned location: {name} at ({x}, {y})"
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1מתודות והתנהגות
מבוא לבלוקי מימושהפרמטר selfמתודות ניתנות לשינויפונקציות משויכותבלוקי מימוש מרוביםשרשור מתודותסיכום – פעולות מלבן4פרויקט: חיית מחמד וירטואלית
הגדרת חיית המחמדהאכלת חיית המחמדתרגלו בעצמכם: קומפיילר Rust אונליין