Referenciák képzése kontruktorokban problémás helyzetekhez vezethet. Ez a leírás segít a bajok elkerülésében.
class Ize { function Ize($nev) { // egy referencia létrehozása a globális $globalref változóban global $globalref; $globalref[] = &$this; // a név beállítása a kapott értékre $this->nevBeallitas($nev); // és kiírás $this->nevKiiras(); } function nevKiiras() { echo "<br>",$this->nev; } function nevBeallitas($nev) { $this->nev = $nev; } } |
Nézzük, hogy van-e különbség az $obj1 és az $obj2 objektum között. Az előbbi a = másoló operátorral készült, az utóbbi a =& referencia operátorral készült.
$obj1 = new Ize('konstruktorban beállított'); $obj1->nevKiiras(); $globalref[0]->nevKiiras(); /* kimenete: konstruktorban beállított konstruktorban beállított konstruktorban beállított */ $obj2 =& new Ize('konstruktorban beállított'); $obj2->nevKiiras(); $globalref[1]->nevKiiras(); /* kimenete: konstruktorban beállított konstruktorban beállított konstruktorban beállított */ |
Szemmel láthatóan nincs semmi különbség, de valójában egy nagyon fontos különbség van a két forma között: az $obj1 és $globalref[0] _NEM_ referenciák, NEM ugyanaz a két változó. Ez azért történhet így, mert a "new" alapvetően nem referenciával tér vissza, hanem egy másolatot ad.
Megjegyzés: Nincsenek teljesítménybeli problémák a másolatok visszaadásakor, mivel a PHP 4 és újabb verziók referencia számlálást alkalmaznak. Legtöbbször ellenben jobb másolatokkal dolgozni referenciák helyett, mivel a referenciák képzése eltart egy kis ideig, de a másolatok képzése gyakorlatilag nem igényel időt. Ha egyik sem egy nagy tömb, vagy objektum, és a változásokat nem szeretnéd mindegyik példányban egyszerre látni, akkor másolatok használatával jobban jársz.
// Most megváltoztatjuk a nevet. Mit vársz? // Számíthatsz arra, hogy mind $obj1 és $globalref[0] megváltozik... $obj1->nevBeallitas('kívülről beállítva'); // mint korábban írtuk, nem ez a helyzet $obj1->nevKiiras(); $globalref[0]->nevKiiras(); /* kimenet: konstruktorban beállított kívülről beállítva */ // lássuk mi a különbség az $obj2 és $globalref[1] esetén $obj2->nevBeallitas('kívülről beállítva'); // szerencsére ezek nem csak egyenlőek, hanem éppen ugyan az // a két változó, így $obj2->nev és $globalref[1]->nev ugyanaz $obj2->nevKiiras(); $globalref[1]->nevKiiras(); /* kimenete: kívülről beállítva kívülről beállítva */ |
Végül még egy utolsó példa, próbáld meg megérteni.
class A { function A($i) { $this->ertek = $i; // próbáld meg kitalálni, miért nem kell itt referencia $this->b = new B($this); } function refLetrehozas() { $this->c = new B($this); } function ertekKiiras() { echo "<br>",get_class($this),' osztály: ',$this->value; } } class B { function B(&$a) { $this->a = &$a; } function ertekKiiras() { echo "<br>",get_class($this),' osztály: ',$this->a->value; } } // próbáld meg megérteni, hogy egy egyszerű másolás // miért okoz nem várt eredményeket a *-al jelölt sorban $a =& new A(10); $a->refLetrehozas(); $a->ertekKiiras(); $a->b->ertekKiiras(); $a->c->ertekKiiras(); $a->ertek = 11; $a->ertekKiiras(); $a->b->ertekKiiras(); // * $a->c->ertekKiiras(); /* kimenete: A osztály: 10 B osztály: 10 B osztály: 10 A osztály: 11 B osztály: 11 B osztály: 11 */ |