Hlavní navigace

Na co si dát pozor při práci s objekty v PHP

Miroslav Holý 9. 10. 2003

Cílem tohoto článku je upozornit na některé nezvyklé vlastnosti práce s objekty v PHP, jejich důsledky a možná řešení.

Uvedené skutečnosti vycházejí z práce s PHP verze 4.3.3.

Skrývání informací a implementace

Jedná se o jednu ze základních vlastností objektů. Ty mají být schopny navenek jednat prostřednictvím svého rozhraní a operace a atributy sloužící pouze jejich interní potřebě skrývat před okolím. PHP nedovoluje skrývat atributy a operace (private). V PHP jsou všechny atributy a operace veřejné! Možným řešením je využívat vlastních konvencí pro názvy operací a atributů, specifikaci zapsat do komentáře nebo použít dokumentační systém jako například Phpdocumentor. Phpdocumentor je obdoba Javadoc určená pro PHP. Dovoluje přiřadit operaci či atributu viditelnost. Pozor, údaje platí pouze pro dokumentaci, v rámci PHP je vše při starém.

Přiřazení

Přiřazení $objekt2=$objekt nepředá odkaz, ale hodnotu. PHP vlastně vytvoří nový objekt $objekt2 a do něj zkopíruje stav objektu $objekt. Nezbývá než používat konstrukce jako $objekt2=&$objekt, function &vratObjekt(), function (&$parametrOb­jekt) apod.

Identita objektu

Každý objekt má svůj vlastní jedinečný identifikátor (handle). Pro PHP je oním identifikátorem de facto název objektu (proměnné). V tomto ohledu PHP pracuje s objekty jako s primitivními typy. Ostatně jako při přiřazování. Chování PHP demonstruje následující ukázka.

Class A {
    var $a;
    function a() {
    $this->a=rand(0,100);
    }
    function getA() {
    return $this->a;
    }
}
$a=new A;
$b=&$a;
$a=new A;
echo $a->getA()."&#60br&#62";
echo $b->getA()."&#60br&#62";

Program vypíše vždy stejné hodnoty. Řešením je buď přiřadit hodnotu ($b=$a), nebo instanci třídy A podruhé nepojmenovat $a, ale zvolit jiné jméno. Uvedená vlastnost se nepříjemně projeví zejména při agregaci.

Class A {
    var $a;
    function a() {
    $this->a=rand(0,100);
    }
    function getA() {
    return $this->a;
    }
}

Class B {
    var $pole = array();
    function b() {
    for ($i=1;$i<=10;$i++) {
            $a=new A;
        array_push($this->pole,&$a);
        }
    }

    function nakresliB() {
    foreach ($this->pole as $a) {
    echo $a->getA()."&#60br&#62";
        }
    }
}

$b=new B;
$b->nakresliB();

Program vypíše stejné hodnoty. Nezbývá než vkládat do pole hodnoty místo odkazů, nebo nevytvářet při každém průchodu cyklu objekt s názvem $a, ale například objekt jako prvek pole $a, tedy $a[$i].

Délka života objektu

V PHP je životnost objektu spjata s během skriptu na webovém serveru. V praxi tedy objekt žije od kliknutí na odkaz uživatelem po zobrazení příslušné stránky na jeho prohlížeči. Naštěstí PHP umožňuje objekty serializovat a ukládat například do session proměnných. Tak můžeme pracovat s jedním objektem během celého sezení. Pro práci s objekty v rámci sezení lze využít následující konstrukce.

Nejdříve zjistíme, zda v session proměnné „a“ je příslušný objekt uložen. Pokud ne, vytvoří se nový, jinak se obnoví ze session proměnné.

if ($_SESSION['a']=="") {
        $a = new A;
} else {
        $a = $_SESSION['a'];

Na konci skriptu objekt $a uložíme zpět do session proměnné „a“.

$_SESSION['a']=$a;

PHP ukládá stav daného objektu i objektů, které jsou obsaženy v jeho proměnných nebo na které jeho proměnné ukazují. Je-li uložen objekt stádo skotu, který obsahuje pole krávy s prvky ukazujícími na jednotlivé objekty krav a pole býci, které obsahuje ve svých prvcích hodnoty objektů třídy býk, uloží se jak krávy, tak býci. Chování demonstruje následující příklad.

Class A {
    var $a;

    function a() {
    $this->a=rand(0,100);
    }

    function getA() {
    return $this->a;
    }
}

Class B {
    var $b;
    var $c;

    function b() {
        $a=new A;
    $this->b=$a;
    }

    function nakresliB() {
    echo $this->b->getA()."&#60br&#62";
    }

    function nakresliC() {
    echo "&#60br&#62".$this->c->getA()."&#60br&#62";
    }

    function setC(&$c) {
    $this->c=&$c;
    }
}

session_start();

if ($_SESSION['b']=="") {
    $b = new B;
    $c = new A;
    $b->setC($c);
} else {
    $b = $_SESSION['b'];
}
$b->nakresliB();
$b->nakresliC();
echo '&#60;br&#62;&#60;br&#62;&#60;a href="pokus.php"&#62;více&#60;/a&#62;';
$_SESSION['b']=$b;

Po každém kliknutí na odkaz „více“, který opět spustí uvedený skript pokus.php, se zobrazí stejný pár čísel.

Vícenásobná dědičnost

PHP nepodporuje vícenásobnou dědičnost ani nepovoluje vícenásobné dědění odpovědnosti, jako např. java pomocí „implements“.

Přetěžování

PHP nepodporuje přetěžování.

Abstraktní třídy

PHP nezná pojem abstraktní třídy, ale umí přepisování. To dovoluje definovat „abstraktní“ třídu jako běžnou třídu a v potomcích operace přepsat a naplnit je požadovaným obsahem.

Závěr

PHP vyžaduje od programátora jistou dávku disciplíny, a to zejména při kooperaci více lidí v rámci projektu. Práce s objekty v PHP má svá specifika, na která je třeba si zvyknout, nicméně nejsou zde překážky, které by objektově orientovanou tvorbu vysloveně komplikovaly.

Našli jste v článku chybu?

16. 5. 2005 10:10

uživatel si přál zůstat v anonymitě
nevim proc se mi tam ne jednou obevila tato stranka chci mit za domovskou stranku mit seznam tak mi to plosíííííím udelajte dekuji

17. 10. 2003 14:17

Jirka Hradil (neregistrovaný)

Tak ted nevim, co byste si presne predstavoval. Chcete primitivni datove typy? Tak je pouzivejte takove, jake jsou. Rad byste objekty? Mate je tam. Pokud chce zapouzdrit primitivni datovy typ, mate moznost. Pokud se vam nelibi pocitat s objektovou reprezentaci, tak si nestezujte, ze ji nemate. ;)
Jestli mate konkretni navrh, jak udelat v tomto smeru zmenu v jazyku Java, poslete ji do Sunu s kopii na me, chytri panove v Sunu to jiste uvitaji. Muj nazor je takovy, ze soucasne reseni je to naprost…

Lupa.cz: Seznam mění vedení. Pavel Zima v čele končí

Seznam mění vedení. Pavel Zima v čele končí

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

Root.cz: 250 Mbit/s po telefonní lince, když máte štěstí

250 Mbit/s po telefonní lince, když máte štěstí

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET

Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

Lupa.cz: UX přestává pro firmy být magie

UX přestává pro firmy být magie

Vitalia.cz: Tesco: Chudá rodina si koupí levné polské kuře

Tesco: Chudá rodina si koupí levné polské kuře

Podnikatel.cz: Chtějte údaje k dani z nemovitostí do mailu

Chtějte údaje k dani z nemovitostí do mailu

Vitalia.cz: Dáte si jahody s plísní?

Dáte si jahody s plísní?

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Podnikatel.cz: Babiš: E-shopy z EET možná vyjmeme

Babiš: E-shopy z EET možná vyjmeme

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Root.cz: Certifikáty zadarmo jsou horší než za peníze?

Certifikáty zadarmo jsou horší než za peníze?

Lupa.cz: Google měl výpadek, nejel Gmail ani YouTube

Google měl výpadek, nejel Gmail ani YouTube

Podnikatel.cz: Na poslední chvíli šokuje výjimkami v EET

Na poslední chvíli šokuje výjimkami v EET

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte