Deep copy e Shallow Copy - OOP in PHP

Deep copy e Shallow Copy - OOP in PHP

Cosa sono le Shallow Copy di un Oggetto?

Una shallow copy di un oggetto crea una nuova variabile che fa riferimento allo stesso oggetto dell'originale. Ciò significa che qualsiasi modifica effettuata all'oggetto originale si rifletterà anche nella copia, e viceversa.

Sintassi di shallow Copy di un Oggetto

La sintassi per effettuare una shallow copy di un oggetto in PHP è la seguente:

$copia = $oggetto_originale;

Esempio con shallow copy di un oggetto in PHP

<?php
// Shallow copy : Copia Superficiale - Se viene modificato l'oggetto copiato, viene modificato pure l'originale.
class User {
    public string $nome;
    public int $id;
    public Skills $userSkills;

    public function __construct(string $nome, array $userSkills){
        $this->nome = $nome;
        $this->id = rand(1,1000);
        $this->userSkills = new Skills([$userSkills]);
    }
}

class Skills {
    public function __construct(public array $competenze){     
    }
}

$utente1 = new User("Donato",['HTML','CSS']);
$utente2 = $utente1; 
$utente2->nome = "Andrea";
$utente2->userSkills->competenze = ['Javascript','PHP'];
var_dump($utente1,$utente2);

/*Output:
object(User)#1 (3) {
  ["nome"]=> string(6) "Andrea"
  ["id"]=> int(95)
  ["userSkills"]=> object(Skills)#2 (1) {
    ["competenze"]=> array(2) {
      [0]=> string(10) "Javascript"
      [1]=> string(3) "PHP"
    }
  }
}
object(User)#1 (3) {
  ["nome"]=> string(6) "Andrea"
  ["id"]=> int(95)
  ["userSkills"]=> object(Skills)#2 (1) {
    ["competenze"]=> array(2) {
      [0]=> string(10) "Javascript"
      [1]=> string(3) "PHP"
    }
  }
 */
  1. Creiamo una classe User che contiene:
  • Una proprietà di tipo stringa $nome
  • Una proprietà di tipo intero $id
  • Una proprietà di tipo Oggetto (classe Skills) che contiene $userSkills;

Tramite il metodo magico __costruct diamo in input l'argomento stringa $nome e l'array $userSkills e :

  • Assegniamo il valore dell'argomento nome alla proprietà $nome
  • Assegniamo un numero random da 1 a 1000 alla proprietà $id
  • Istanziamo un oggetto che passa come argomento l'array $userSkills

Creiamo una classe Skills che contiene un metodo magico costruttore, che prende come parametro un array con visibilità pubblica.

Istanziamo un oggetto chiamato $utente1 e passiamo in input il nome Donato e l'array HTML e CSS

Facciamo una Shallow Copy (copia superficiale) di $utente1 e la chiamiamo $utente2 (usiamo l'operatore = )

Di utente2: rinominiamo il nome e le competenze.

Facciamo un var_dump dei due oggetti e possiamo vedere dall'output che se si modificano i valori di utente2, automaticamente, vengono modificati anche i valori di utente1.

Cosa sono le Deep Copy di un Oggetto?

Una deep copy di un oggetto crea una nuova variabile che contiene una copia completa dell'oggetto originale, allocando quindi nuova memoria. Ciò significa che qualsiasi modifica effettuata all'oggetto originale non influirà sulla copia, e viceversa.

Sintassi di Deep Copy di un Oggetto

La sintassi per effettuare una deep copy di un oggetto in PHP è la seguente:

$nuova_variabile = clone $oggetto_originale;

Si noti che la parola chiave clone viene utilizzata per creare una copia profonda di un oggetto, in modo da copiare tutti i valori delle proprietà dell'oggetto.

Esempio con Deep copy di un oggetto in PHP

<?php
/* DEEP copy: crea una copia INDIPENDENTE dell'oggetto originale, 
compresi tutti i suoi dati e le sue proprietà. In questo modo, le modifiche apportate 
ad uno degli oggetti non influiscono sull'altro. */

// Creazione di una classe User
class User{
    public int $id; // Definiamo una proprietà di tipo intero $id
    public string $name; // Definiamo una proprietà di tipo stringa $name
    public Skills $skillsInstance; // Definiamo una proprietà ($skillsInstance) di tipo Skills (Classe)

    // Creiamo un oggetto con il metodo magico construct che prende in input gli argomenti: stringa $name e array $competenze
    public function __construct(string $name, array $competenze){
        // Assegniamo alla proprietà $name l'argomento passato in input $name
        $this->name = $name;
        // Assegnamo alla proprietà $id un numero random da 1 a 10000
        $this->id = rand(1,10000); 
        // Assegniamo alla proprietà skillsInstance il compito di creare un istanza
        // della classe Skills passando in input l'argomento $competenze al costruttore di Skills
        $this->skillsInstance = new Skills($competenze);
    }

    // Creiamo con il metodo magico __clone una DEEP COPY (quindi indipendente)
    // dell'oggetto.
    public function __clone(){
        // assegniamoci un nuovo id casuale da 1 a 10000
        $this->id = rand(1,10000);
        // definiamo un nuovo nome per l'utente clonato
        $this->name = "Utente Clonato";
        // creiamo una nuova istanza della classe Skills, passando in input
        // un array vuoto , che verrà riempito con l'argomento $competenze
        // contenuto all'interno del metodo magico construct della classe Skills
        $this->skillsInstance = new Skills([]);
    }
}

// Creiamo la classe Skills
class Skills{
    // Definiamo con il metodo magico un oggetto che prende come argomento 
    // l'array $competenze.
    function __construct(public array $competenze){
    }
}

// Creiamo un nuovo oggetto con la classe user, e passiamo in input la stringa $name e l'array $competenze
$user1 = new User("Utente 1",['HTML5','CSS3']);
// cloniamo con DEEP COPY l'user1
$user2 = clone $user1;
// definiamo per l'oggetto user2 un nuovo array di $competenze
$user2->skillsInstance->competenze = ['Javascript','jQuery'];
$user3 = clone $user2;
$user3->skillsInstance->competenze = ['PHP','Laravel'];

var_dump($user1,$user2,$user3);
?>
/* Output
object(User)#1 (3) {
  ["id"]=>int(5512)
  ["name"]=>string(8) "Utente 1"
  ["skillsInstance"]=>object(Skills)#2 (1) {
    ["competenze"]=>array(2) {
      [0]=>string(5) "HTML5"
      [1]=>string(4) "CSS3"
    }
  }
}
object(User)#3 (3) {
  ["id"]=>int(3044)
  ["name"]=>string(14) "Utente Clonato"
  ["skillsInstance"]=> object(Skills)#4 (1) {
    ["competenze"]=> array(2) {
      [0]=>string(10) "Javascript"
      [1]=>string(6) "jQuery"
    }
  }
}
object(User)#5 (3) {
  ["id"]=>int(9192)
  ["name"]=>string(14) "Utente Clonato"
  ["skillsInstance"]=>object(Skills)#6 (1) {
    ["competenze"]=>array(2) {
      [0]=>string(3) "PHP"
      [1]=>string(7) "Laravel"
    }
  }
}
*/

Quali sono le principali differenze tra Shallow copy e Deep Copy su un Oggetto.

In PHP, la shallow copy e la deep copy sono due modi differenti di copiare i dati da una variabile a un'altra. La shallow copy crea una copia della variabile originale che punta allo stesso spazio di memoria, mentre la deep copy crea una nuova variabile con un nuovo spazio di memoria che contiene una copia indipendente dei dati dell'originale.

Per effettuare una deep copy in PHP, si utilizza la parola chiave clone, come già visto. Quando si utilizza clone, PHP crea una nuova istanza della classe dell'oggetto che si sta clonando e copia il valore di tutte le proprietà dell'oggetto originale. La sintassi per la deep copy in PHP è la seguente:

phpCopy code$nova_variabile = clone $variabile_originale;

Oltre alla parola chiave clone, esiste anche un metodo magico chiamato __clone(), che consente di personalizzare il comportamento della deep copy per una specifica classe. Quando viene definito il metodo __clone() all'interno di una classe, questo viene chiamato ogni volta che si effettua una deep copy dell'oggetto della classe.

Il metodo __clone() ha il compito di personalizzare il comportamento della deep copy, permettendo ad esempio di clonare solo alcune proprietà dell'oggetto originale o di inizializzare delle nuove proprietà. La sintassi del metodo __clone() è la seguente:

phpCopy codepublic function __clone() {
    // personalizzazione del comportamento della deep copy
}

In sintesi, la differenza tra la shallow copy e la deep copy in PHP sta nel modo in cui viene copiata la variabile originale. La shallow copy crea una copia che punta allo stesso spazio di memoria dell'originale, mentre la deep copy crea una nuova variabile con un nuovo spazio di memoria che contiene una copia indipendente dei dati dell'originale. La parola chiave clone viene utilizzata per la deep copy, mentre il metodo magico __clone() permette di personalizzare il comportamento della deep copy per una specifica classe.

Scritto da Donato Pirolo

Ciao, sono Donato, frontend developer con una smisurata passione per la SEO. Creo strumenti ad hoc per aiutare aziende e professionisti ad essere cercati sul web e trovare clienti.

Potrebbero interessarti

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Copyright © 2023
linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram