Podręcznik PHP
Poprzedni
Rozdział 14.
Klasy i Obiekty
Następny
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.
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 =...
$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).
/ / 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ć /
class A {function A($i) {$this - wartosc = $i; / / domyśl się dlaczego nie potrzebujemy tutaj referencji $this - b = new B($this);} function stworzRef() {$this - c = new B($this);} function wyswietlWartosc() {echo "br" ,"klasa ",get_class($this) ,': ',$this - value;}} class B {function B ($a) {$this - a = $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(); / * wyjście: klasa A:
10 klasa B:
10 klasa B:
10 klasa A:
11 klasa B:
11 klasa B:
Poprzedni
Spis treści
Następny
Magiczne funkcje __sleep i __wakeup
Początek rozdziału