Menu
Coddy logo textTech

העמקה בשכפול אובייקטים

חלק מהיחידה תכנות מונחה עצמים במסלול ה-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 כדי להשיג עצמאות אמיתית בין המקור לעותק.

challenge icon

אתגר

קל

בואו נבנה מערכת לניהול מסמכים שמדגימה את ההבדל בין שכפול שטחי לשכפול עמוק. תיצרו מסמכים שמכילים מידע על המחבר, ותוודאו ששכפול של מסמך יוצר עותק עצמאי באמת.

תארגנו את הקוד שלכם בשלושה קבצים:

  • 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: הדפיסו את פרטי המסמך המשוכפל

?>
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר PHP אונליין