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
*/ |