Referencje - kopiowanie obiektów

Operator new tworzy obiekt danej klasy.Jako efekt zwraca referencję, czyli adres w pamięci nowo utworzonego obiektu.

Wykonanie kodu :


<?php 
class Klasa{
    public $nazwa;
}
$pierwszyObiekt = new Klasa; //1
$drugiObiekt->nazwa = 'pierwsza';
$drugiObiekt = $pierwszyObiekt; //2
$drugiObiekt->nazwa = 'druga'; //3
echo '$nazwa w $pierwszyObiekt 
        = '.$pierwszyObiekt->nazwa;
unset($druaKlasa);
?>

Na ekranie ujrzymy :

$nazwa w $pierwszyObiekt = druga;

Funkcje a obiekty

Gdy przesyłamy jako argument do funkcji zmienną zawierającą referencję do obiektu klasy jest ona automatycznie przesyłana przez referencję.

Tak więc w ciele funkcji działamy na oryginalnym obiekcie a nie na jego kopii.


<?php class Klasa{
    public $wartosc;
}
/////////////////////////
function zmieniam($klasa){
$klasa->wartosc = 20;
}
////////////////////////
$klasa = new Klasa;
zmieniam($klasa);
echo $klasa->wartosc;
?>

Na ekranie ujrzymy :

20

Kopiowanie obiektów

Do kopiowania obiektów służy polecenie clone. Używamy go gdy chcemy przypisać do zmiennej kopie obiektu, zamiast jego referencji, lub gdy do funkcji przesyłamy kopie obiektu, nie chcąc by ta pracowała na oryginale i miała możliwość zmian.

Polecenie copy tworzy lustrzaną kopię obiektu a następnie, wykonuję funkcję __clone() jeśli takowa jest zdeklarowana w klasie. Następnie przesyła referencję do nowo utworzonego obiektu do zmiennej bądź do funkcji.


<?php
class Klasa1{
    public $wartosc;
    function __construct($wartosc){
         $this->wartosc = $wartosc;
    }
    function __destruct(){
        echo 'gine, moja wartosc podczas 
            konania to '.$this->wartosc;
    }

}
class Klasa2{
    public $wartosc;
    function __construct($wartosc){
         $this->wartosc = $wartosc;
    }
    function __clone(){
        $this->wartosc += 20;
    }

}
function zmien($klasa){
 $klasa->wartosc *= -1;
}
$zmienna=new Klasa1(10); //1
zmien(clone $zmienna); //2
echo 'wartosc oryginalu po wywolaniu funkcji 
     '.$zmienna->wartosc.'<br />'; //3
$zmienna2 = new Klasa2(0);//4
$kopia = clone $zmienna2; //5
echo '$wartosc w kopii = '.$kopia->wartosc; //6
?>

Na ekranie zobaczymy :

gine, moja wartosc podczas konania to -10
wartosc oryginalu po wywolaniu funkcji 10
$wartosc w kopii = 20
gine, moja wartosc podczas konania to 10

Agregaty raz jeszcze

Gdy wywołujemy clone dla klasy zawierającej obiekty innych klas (agregaty), należy pamiętać by w metodzie __clone() wywołać polecenie clone dla obiektów zawieranych, w innym wypadku kopia będzie posiadać referencję do obiektów zawieranych w oryginale.


<?
class Bateria{
    //cialo klasy
}
class Pilot{
    public $bateria = new Bateria;
    function __clone(){
        $this->bateria = clone $this->bateria;
    }
}
?>

Jak to działa ? Najpierw wykonywana jest dokładna kopia obiektu, właściwość po właściwośći, tak więc baterii, jako że przechowuje referencję do obiektu przypisany zostanie taki sam adres jak w obiekcie kopiowanym. Następnie rusza do walki metoda __clone(), która bateri przypisuje jej kopie. Gdybyśmy nie napisali metody __clone, wyczerpanie baterii w kopiowanym obiekcie niosło by za sobą wyczerapnie baterii w kopii i odwrotnie. Pomyśl co by się stało gdyby któryś z obiektów został usunięty...

Operator ===

PHP rozróżnia obiekty za pomocą ich jednoznacznych ID, które są nadawane automatycznie podczas ich tworzenia.

Za pomocą operatora === możemy spradzić czy dane zmienne przechowują referencję do tych samych obiektów. Operator ten porównuje ID obiektów.


<?php
$zmienna = new Klasa;
$zmienna2 = $zmienna;
echo (int)$zmienna2 === $zmienna.'<br />';
$zmienna2=clone $zmienna;
echo (int)$zmienna2 === $zmienna.'<br />';

?>

Na ekranie ujrzymy :

1
0