Menu
Coddy logo textTech

Dogłębne omówienie klonowania obiektów

Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 61 z 91.

Wcześniej w tym kursie poznano magiczną metodę __clone. Teraz przyjrzyjmy się kluczowej różnicy między klonowaniem płytkim a głębokim, gdy obiekty zawierają inne obiekty jako właściwości.

Domyślnie podczas klonowania PHP wykonuje płytką kopię. Wartości skalarne są duplikowane, ale właściwości obiektów pozostają referencjami do tych samych obiektów:

<?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;

Wynik:

Alice - London

Zauważ, że zmiana $clone->name nie wpłynęła na oryginał, ale zmiana miasta w adresie już tak! Oba obiekty współdzielą tę samą instancję Address.

Aby utworzyć głęboką kopię, w której zagnieżdżone obiekty również są klonowane, zaimplementuj __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;

Wynik:

Paris

Teraz każda Person ma własny, niezależny obiekt Address. Gdy obiekty zawierają wiele zagnieżdżonych obiektów, musisz sklonować każdy z nich w __clone, aby zapewnić pełną niezależność oryginału i kopii.

challenge icon

Wyzwanie

Łatwy

Stwórzmy system zarządzania dokumentami, który pokazuje różnicę między płytkim a głębokim klonowaniem. Utworzysz dokumenty zawierające informacje o autorze i zadbasz o to, by sklonowanie dokumentu tworzyło naprawdę niezależną kopię.

Rozmieścisz swój kod w trzech plikach:

  • Author.php: Utwórz klasę Author, która reprezentuje autora dokumentu. Użyj promocji konstruktora, aby zdefiniować publiczne $name (string) i publiczne $email (string).
  • Document.php: Utwórz klasę Document, która zawiera autora. Dołącz plik Author. Klasa powinna:
    • Użyć promocji konstruktora dla publicznego $title (string) i publicznego $author (Author)
    • Zaimplementować magiczną metodę __clone(), aby wykonywać głębokie klonowanie; gdy dokument jest klonowany, jego autor również powinien zostać sklonowany, tak aby zmiany w autorze kopii nie wpływały na oryginał
    • Mieć metodę getInfo(), która zwraca "[title] by [author name] ([author email])"
  • main.php: Dołącz plik Document. Otrzymasz trzy dane wejściowe: tytuł dokumentu, imię i nazwisko autora oraz adres e-mail autora.

    Utwórz obiekt Document z obiektem Author, korzystając z podanych danych wejściowych. Sklonuj dokument, a następnie zmodyfikuj imię i nazwisko autora kopii, dopisując do niego " (Copy)", i zmień tytuł kopii, dodając na początku "Copy of ".

    Wypisz dwa wiersze:

    • Informacje o oryginalnym dokumencie
    • Informacje o sklonowanym dokumencie

    Jeśli głębokie klonowanie jest zaimplementowane poprawnie, autor oryginalnego dokumentu powinien pozostać bez zmian nawet po zmodyfikowaniu autora kopii.

To wyzwanie pokazuje, dlaczego głębokie klonowanie jest ważne. Bez prawidłowej implementacji __clone() oba dokumenty współdzieliłyby ten sam obiekt Author, a zmiana jednego wpłynęłaby na drugi.

Spróbuj swoich sił

<?php

require_once 'Document.php';

// Odczytaj dane wejściowe
$title = trim(fgets(STDIN));
$authorName = trim(fgets(STDIN));
$authorEmail = trim(fgets(STDIN));

// TODO: Utwórz obiekt Author z podanym imieniem i nazwiskiem oraz adresem e-mail

// TODO: Utwórz obiekt Document z podanym tytułem i obiektem Author

// TODO: Sklonuj dokument

// TODO: Zmień imię i nazwisko autora klonu, dopisując na końcu " (Copy)"

// TODO: Zmień tytuł klonu, dodając na początku "Copy of "

// TODO: Wyświetl informacje o oryginalnym dokumencie

// TODO: Wyświetl informacje o sklonowanym dokumencie

?>
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator PHP online