העמקה בשכפול אובייקטים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-PHP של Coddy. שיעור 61 מתוך 91.
למדת על המתודה הקסומה __clone מוקדם יותר בקורס הזה. עכשיו נבחן את ההבדל החשוב בין שכפול רדוד לשכפול עמוק כאשר אובייקטים מכילים אובייקטים אחרים כמאפיינים.
כברירת מחדל, PHP מבצעת העתקה שטחית בעת שכפול. ערכים סקלריים משוכפלים, אך מאפייני אובייקט נשארים הפניות לאותם אובייקטים:
<?php
class Address {
public function __construct(public string $city) {}
}
class Person {
public function __construct(
public string $name,
public Address $address
) {}
}
$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;
$clone->name = "Bob";
$clone->address->city = "London";
echo $original->name . " - " . $original->address->city;
פלט:
Alice - Londonשימו לב ששינוי $clone->name לא השפיע על המקור, אבל שינוי העיר בכתובת כן! שני האובייקטים חולקים את אותו מופע של Address.
כדי ליצור עותק עמוק שבו גם אובייקטים מקוננים משוכפלים, יש לממש את __clone:
<?php
class Person {
public function __construct(
public string $name,
public Address $address
) {}
public function __clone(): void {
$this->address = clone $this->address;
}
}
$original = new Person("Alice", new Address("Paris"));
$clone = clone $original;
$clone->address->city = "London";
echo $original->address->city;
פלט:
Parisכעת לכל Person יש Address עצמאי משלו. כאשר האובייקטים שלך מכילים כמה אובייקטים מקוננים, עליך לשכפל כל אחד מהם בתוך __clone כדי להשיג עצמאות אמיתית בין המקור לעותק.
אתגר
קלבואו נבנה מערכת לניהול מסמכים שמדגימה את ההבדל בין שכפול שטחי לשכפול עמוק. תיצרו מסמכים שמכילים מידע על המחבר, ותוודאו ששכפול של מסמך יוצר עותק עצמאי באמת.
תארגנו את הקוד שלכם בשלושה קבצים:
Author.php: צרו מחלקהAuthorשמייצגת את המחבר של מסמך. השתמשו בקידום פרמטרים בבנאי כדי להגדיר$nameמסוג מחרוזת כמאפיין ציבורי ו-$emailמסוג מחרוזת כמאפיין ציבורי.Document.php: צרו מחלקהDocumentשמכילה מחבר. כללו את הקובץ Author. על המחלקה:- להשתמש בקידום פרמטרים בבנאי עבור
$titleמסוג מחרוזת כמאפיין ציבורי ועבור$authorמסוג Author כמאפיין ציבורי - לממש את מתודת הקסם
__clone()כדי לבצע שכפול עמוק: כאשר מסמך משוכפל, יש לשכפל גם את המחבר שלו, כך ששינויים במחבר של העותק לא ישפיעו על המקור - להכיל מתודה
getInfo()שמחזירה"[title] by [author name] ([author email])"
- להשתמש בקידום פרמטרים בבנאי עבור
main.php: כללו את הקובץ Document. תקבלו שלוש קלטים: כותרת של מסמך, שם של מחבר וכתובת אימייל של מחבר.צרו
DocumentעםAuthorבאמצעות הקלט שסופק. שכפלו את המסמך, ואז שנו את שם המחבר של העותק על ידי הוספת" (Copy)"בסופו, ושנו את כותרת העותק על ידי הוספת"Copy of "בתחילתה.הדפיסו שתי שורות:
- המידע של המסמך המקורי
- המידע של המסמך המשוכפל
אם מימשתם שכפול עמוק כראוי, המחבר של המסמך המקורי אמור להישאר ללא שינוי גם לאחר שינוי המחבר של העותק.
האתגר הזה מדגים מדוע שכפול עמוק חשוב: ללא מימוש תקין של __clone(), שני המסמכים ישתפו את אותו אובייקט Author, ושינוי באחד מהם ישפיע על השני.
נסו בעצמכם
<?php
require_once 'Document.php';
// קראו את הקלטים
$title = trim(fgets(STDIN));
$authorName = trim(fgets(STDIN));
$authorEmail = trim(fgets(STDIN));
// TODO: צרו Author עם השם וכתובת האימייל שסופקו
// TODO: צרו Document עם הכותרת שסופקה ועם ה-Author
// TODO: שכפלו את המסמך
// TODO: שנו את שם המחבר של העותק המשוכפל על ידי הוספת " (Copy)" בסופו
// TODO: שנו את כותרת העותק המשוכפל על ידי הוספת "Copy of " בתחילתה
// TODO: הדפיסו את פרטי המסמך המקורי
// TODO: הדפיסו את פרטי המסמך המשוכפל
?>השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים (OOP)
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםמילת המפתח $thisמתודותמאפייניםבנאי (__construct)הורס (__destruct)חזרה: מחשבון פשוט4ירושה
ירושה בסיסיתמילת המפתח parent::דריסת מתודותמילת המפתח finalמחלקות מופשטותסיכום – היררכיית עובדים7כימוס
ציבורי, מוגן, פרטימפרטי גישה לעומקמתודות גישה ועדכוןהסתרת מידעקידום פרמטרים בבנאי (8.0)סיכום – מערכת רישומי תלמידים10מושגי OOP מתקדמים
הרכבה לעומת ירושההזרקת תלויותמחלקות אנונימיותטיפוסי Enum (PHP 8.1)סיבים (PHP 8.1)העמקה בשכפול אובייקטיםמחוללים ואיטרטורים2מרחבי שמות וטעינה אוטומטית
מבוא למרחבי שמותמילת המפתח useתקן הטעינה האוטומטית PSR-4הטוען האוטומטי של Composerסיכום – פרויקט מאורגן5ממשקים וחוזים
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםממשק לעומת מחלקה מופשטתרמזי טיפוסים עם ממשקיםסיכום - מחשבון צורות8מתודות קסם
מבוא למתודות קסם__toString ו־__debugInfo__get, __set, __isset, __unset__call ו־__callStatic__clone ושיבוט אובייקטים__serialize ו־__unserializeסיכום – אוסף מותאם אישית3מאפייני מחלקה
מאפייני מופע לעומת מאפיינים סטטייםקבועים במחלקותמתודות ומאפיינים סטטייםמאפיינים פרטיים ומוגניםמאפיינים לקריאה בלבד (PHP 8.1)סיכום – מנהל חשבון בנק6פולימורפיזם
בחינה מחדש של דריסת מתודותפולימורפיזם באמצעות ממשקיםרמזי טיפוסים וטיפוסי איחודקישור סטטי מאוחרסיכום — מעבד תשלומיםתרגלו בעצמכם: קומפיילר PHP אונליין