PHP kézikönyv
Előző | 18. Fejezet. Osztályok, objektumok | Következő

# Referenciák a konstruktorban

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.

Hogy bebizonyítsuk, amit fent írtunk, lásd az alábbi kódot:

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

Előző | Tartalom | Következő
A speciális __sleep és __wakeup metódusok | Fel | Classes and Objects (PHP 5)