Compzone.Org :: Podręcznik PHP :: Referencje wewnątrz konstruktora
Która technologia najbardziej Cię interesuje?
PHP
ASP
AJAX
SQL
JavaScript
Inna
Sonda Wyniki

Add to Google

Referencje wewnątrz konstruktora

Tworzenie referencji wewnątrz konstruktora może prowadzić do dziwnych efektów. Ten rozdział ma pomóc w unikaniu takich problemów.

<?php
class Foo {
    function 
Foo($nazwa) {
        
// stworz referencje wewnatrz globalnej tablicy $globalref
        
global $globalref;
        
$globalref[] = &$this;
        
// ustaw nazwę na przekazaną wartość
        
$this->ustawNazwe($nazwa);
        
// i wyświetl ją
        
$this->wyswietlNazwe();
    }

    function 
wyswietlNazwe() {
        echo 
"<br />",$this->nazwa;
    }
    
    function 
ustawNazwe($nazwa) {
        
$this->nazwa $nazwa;
    }
}
?>

Sprawdźmy, czy jest jakaś różnica pomiędzy $bar1, który jest tworzony przy pomocy operatora przypisania =, a $bar2, który został stworzony używając operatora referencji =&...

<?php
$bar1 
= new Foo('ustawione w konstruktorze');
$bar1->wyswietlNazwe();
$globalref[0]->wyswietlNazwe();

/* wyjście:
ustawione w konstruktorze
ustawione w konstruktorze
ustawione w konstruktorze */

$bar2 =& new Foo('ustawione w konstruktorze');
$bar2->wyswietlNazwe();
$globalref[1]->wyswietlNazwe();

/* wyjście:
ustawione w konstruktorze
ustawione w konstruktorze
ustawione w konstruktorze */
?>

Wydaje się, że nie ma żadnej różnicy, ale na prawdę jest jedna, i to bardzo istotna: $bar1 i $globalref[0] NIE są referencjami, NIE są tą samą zmienna. Dzieje się tak, ponieważ "new" nie zwraca domyślnie referencji, ale kopię.

Notatka: Zwracanie kopii zamiast referencji nie powoduje utraty wydajności (od PHP 4 używane jest zliczanie referencji). Jednakże zazwyczaj lepiej jest pracować poprostu z kopiami zamiast referencji, poniewać tworzenie referencji zabiera trochę czasu, podczas gdy tworzenie kopii obiektów teoretycznie w ogóle nie zabiera czasu (chyba że któraś z tych zmiennych jest dużą tablicą lub obiektem i jedno z nich ulega zmianie, po czym tej samej zmianie ulegają pozostałe zmienne; wtedy lepiej jest użyć referencji do zmieniania ich równolegle).

Aby udowodnić to, co zostało zapisane powyżej, przyjrzyjmy się poniższemu programowi.
<?php
// teraz zmienimy nazwę. czego się spodziewasz?
// możesz się spodziewać, że i $bar1 i $globalref[0] zmienią swoje nazwy...
$bar1->ustawNazwe('ustawiona z zewnątrz');

// jak napisano powyżej, nic takiego się nie stanie
$bar1->wyswietlNazwe();
$globalref[0]->wyswietlNazwe();

/* wyjście:
ustawiona z zewnątrz
ustawiona w konstruktorze */

// zobaczmy co się dzieje z $bar2 i $globalref[1]
$bar2->ustawNazwe('ustawiona z zewnątrz');

// na szczęście ta zmienna nie zachowuje się jak ta z poprzedniego przypadku
// są to te same zmienne, z więc $bar2->nazwa i $globalref[1]->nazwa są także
// tymi samymi zmiennymi
$bar2->wyswietlNazwe();
$globalref[1]->wyswietlNazwe();

/* wyjście:
ustawiona z zewnątrz
ustawiona z zewnątrz */
?>

Ustatni przykład. Postaraj się go zrozumieć/

<?php
class {
    function 
A($i) {
        
$this->wartosc $i;
        
// domyśl się dlaczego nie potrzebujemy tutaj referencji
        
$this->= new B($this);
    }

    function 
stworzRef() {
        
$this->= new B($this);
    }

    function 
wyswietlWartosc() {
        echo 
"<br />","klasa ",get_class($this),': ',$this->value;
    }
}


class 
{
    function 
B(&$a) {
        
$this->= &$a;
    }

    function 
wyswietlWartosc() {
        echo 
"<br />","klasa ",get_class($this),': ',$this->a->value;
    }
}
// spróbuj zrozumieć dlaczego użycie tu prostego kopiowania może powodować
// nieporządany efekt w linii uznaczonej znaczkiem '*'
$a =& new A(10);
$a->stworzRef();

$a->wyswietlWartosc();
$a->b->wyswietlWartosc();
$a->c->wyswietlWartosc();

$a->value 11;

$a->wyswietlWartosc();
$a->b->wyswietlWartosc(); // *
$a->c->wyswietlWartosc();

?>

Powyższy przykład wyświetli:

klasa A: 10
klasa B: 10
klasa B: 10
klasa A: 11
klasa B: 11
klasa B: 11
Copyright © 2005-2006 Compzone.Org. Kopiowanie i wykorzystywanie materiałów zawartych na tej stronie bez zgody autora zabronione!