__clone e clonazione degli oggetti
Fa parte della sezione Programmazione orientata agli oggetti del percorso PHP di Coddy. Lezione 48 di 91.
Quando assegni un oggetto a un'altra variabile in PHP, non ne crei una copia: entrambe le variabili puntano allo stesso oggetto. Per creare una copia effettivamente indipendente, devi usare la parola chiave clone:
<?php
class Product {
public function __construct(
public string $name,
public float $price
) {}
}
$original = new Product("Laptop", 999.99);
$copy = clone $original;
$copy->price = 899.99;
echo $original->price . " - " . $copy->price;
Output:
999.99 - 899.99Per impostazione predefinita, PHP esegue una copia superficiale: copia direttamente tutti i valori delle proprietà. Funziona correttamente per i valori scalari, ma gli oggetti all'interno del tuo oggetto continuano a fare riferimento alla stessa istanza. Il metodo magico __clone() ti consente di personalizzare questo comportamento:
<?php
class Order {
public function __construct(
public int $id,
public array $items = []
) {}
public function __clone(): void {
$this->id = 0;
$this->items = [];
}
}
$order1 = new Order(101, ["Book", "Pen"]);
$order2 = clone $order1;
echo "Original: " . $order1->id . ", Clone: " . $order2->id;
Output:
Original: 101, Clone: 0Il metodo __clone() viene chiamato sul nuovo oggetto dopo aver effettuato la copia superficiale. È qui che puoi reimpostare gli ID, creare nuove copie degli oggetti annidati o eseguire le operazioni di pulizia necessarie affinché il clone sia davvero indipendente.
Sfida
FacileCreiamo un sistema di versionamento dei documenti che mostra come la clonazione crea copie indipendenti e come il metodo magico __clone() ti permette di personalizzare ciò che accade quando un oggetto viene clonato.
Organizzerai il codice in due file:
Document.php: crea una classeDocumentche rappresenta un documento con versioni. Usa la promozione del costruttore per definire un$titlepubblico (stringa), un$contentpubblico (stringa) e un$versionpubblico (intero, con valore predefinito 1). Aggiungi una proprietà$createdAtprivata che memorizza la data e l'ora correnti (usadate('Y-m-d H:i:s')nel costruttore). Il tuo documento deve avere:getCreatedAt(): restituisce la data e l'ora di creazione__clone(): quando un documento viene clonato, la versione deve aumentare di 1 e$createdAtdeve essere reimpostato alla data e all'ora correnti (il clone è una nuova versione creata «ora»)
main.php: includi il file Document. Riceverai tre input: un titolo, un contenuto e una nuova stringa di contenuto per la versione clonata. Crea unDocumentcon il titolo e il contenuto. Poi clonalo per creare una nuova versione e aggiorna il contenuto del clone con la nuova stringa di contenuto. Stampa quattro righe:- La versione del documento originale
- La versione del documento clonato
- Il contenuto del documento originale
- Il contenuto del documento clonato
Questo sistema mostra come __clone() ti permetta di controllare ciò che accade durante la clonazione. Il documento originale conserva la sua versione e la data di creazione, mentre il clone diventa automaticamente una nuova versione con una data e un'ora aggiornate: l'ideale per tenere traccia della cronologia dei documenti, in cui ogni clone rappresenta una nuova revisione.
Provalo tu
<?php
require_once 'Document.php';
// Leggi gli input
$title = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
$newContent = trim(fgets(STDIN));
// TODO: Crea un Document con il titolo e il contenuto
// TODO: Clona il documento per creare una nuova versione
// TODO: Aggiorna il contenuto del clone con la nuova stringa di contenuto
// TODO: Stampa quattro righe:
// 1. La versione del documento originale
// 2. La versione del documento clonato
// 3. Il contenuto del documento originale
// 4. Il contenuto del documento clonato
?>Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Fondamenti della programmazione orientata agli oggetti
File esterniIntroduzione alla programmazione orientata agli oggettiClassi e oggettiLa parola chiave $thisMetodiProprietàCostruttore (__construct)Distruttore (__destruct)Riepilogo - Calcolatrice semplice4Ereditarietà
Ereditarietà di baseLa parola chiave parent::Sovrascrittura dei metodiLa parola chiave finalClassi astratteRiepilogo - Gerarchia dei dipendenti7Incapsulamento
Pubblico, Protetto, PrivatoApprofondimento sui modificatori di accessoGetter e SetterOccultamento delle informazioniPromozione dei parametri del costruttore (8.0)Riepilogo - Sistema di gestione dei registri degli studenti10Concetti avanzati di programmazione a oggetti
Composizione vs ereditarietàDependency InjectionClassi anonimeEnumerazioni (PHP 8.1)Fibers (PHP 8.1)Approfondimento sulla clonazione degli oggettiGeneratori e iteratori13Modelli di progettazione, parte 2
Modello CommandModello AdapterModello DecoratorModello Template MethodModello StateModello CompositeModello Repository2Namespace e autoloading
Introduzione ai namespaceLa keyword useStandard di autoloading PSR-4Autoloader di ComposerRiepilogo - Progetto organizzato5Interfacce e contratti
Introduzione alle interfacceImplementare le interfacceImplementare più interfacceInterfaccia vs classe astrattaType hinting con le interfacceRiepilogo - Calcolatore di forme8Metodi magici
Introduzione ai metodi magici__toString e __debugInfo__get, __set, __isset, __unset__call e __callStatic__clone e clonazione degli oggetti__serialize e __unserializeRiepilogo - Collezione personalizzata11Sistema dei tipi e gestione degli errori
Dichiarazioni di tipoTipi nullableTipi unione e intersezioneClassi di eccezioneGerarchia di eccezioni personalizzataTry, Catch, FinallyRiepilogo - Validatore di moduli14Progetto: Gestione della biblioteca
Panoramica del progettoClassi Libro e Utente3Proprietà delle classi
Proprietà di istanza e staticheCostanti nelle classiMetodi e proprietà staticiProprietà private e protectedProprietà readonly (PHP 8.1)Riepilogo - Gestore di conti bancari6Polimorfismo
Ridefinizione dei metodi, ripresaPolimorfismo tramite interfacceSuggerimenti sui tipi e tipi UnionBinding statico tardivoRiepilogo - Processore di pagamenti9Tratti
Introduzione ai trattiUtilizzare più trattiRisoluzione dei conflitti tra trattiMetodi astratti nei trattiTratti vs ereditarietà12Design pattern - Parte 1
Introduzione ai design patternPattern SingletonPattern FactoryPattern ObserverPattern StrategyEsercitati da solo: Compilatore PHP online