Objekty v PHP umožňují používat dědičnost. Podívejme se jak a
ukažme si na některá úskalí, která s sebou používání objektů v PHP nese.
5.7.2004 15:00 | Petr Zajíc | přečteno 59192×
V minulém díle našeho seriálu jsme vytvořili objektový kalendář. A
slíbili jsme si, že dnes bude řeč o dědičnosti a nebezpečí spojených s
objekty v PHP. Podívejme se tedy na tyto dva aspekty objektově
orientovaného programování v PHP:
PHP, ostatně jako každý jiný objektově orientovaný jazyk umožňuje
rozšiřovat objekty pomocí mechanizmu dědičnosti. V reálném světě dědí
děti po
rodičích a prarodičích některé vlastnosti, zatímco jinými vlastnostmi
se liší. Kdybychom použili příklad s mobilními telefony, tak můžeme
sestavit následující analogii: Objekt NOKIA 6210 bude potomkem třídy
telefonů s tím, že bude (stejně jako každý jiný telefon) umět vytočit
číslo, přijmout hovor a podobně. Narozdíl od "obecného" telefonu bude
"šedesátdvadesítka" ovšem mít některé vlastnosti a metody, které jsou
pro ni specifické. Tak třeba narozdíl od telefonu na pevné lince může
specifikovat vlastnosti NabijBaterii, PřenesVizitkuPoInfraportu a tak
dále.
V PHP může jedna třída dědit vlastnosti a metody jiné, rodičovské třídy s tím, že některé věci bude dělat jinak a některé bude možná umět navíc. Například bychom chtěli, aby náš skvělý kalendář uměl nejenom dny v měsíci zobrazit, ale aby rovněž uměl některé z nich zvýrazit. To může být užitečné třeba v případě, kdy má kalendář informovat o dnech, v nichž se něco děje. Mělo by to vypadat nějak takhle:
červenec | |||||
Po | 5 | 12 | 19 | 26 | |
Út | 6 | 13 | 20 | 27 | |
St | 7 | 14 | 21 | 28 | |
Čt | 1 | 8 | 15 | 22 | 29 |
Pá | 2 | 9 | 16 | 23 | 30 |
So | 3 | 10 | 17 | 24 | 31 |
Ne | 4 | 11 | 18 | 25 |
Půjdeme na to tak, že vyvineme novou třídu, nazvanou lepsi_kalendar, která bude danou vlastnost implementovat. Třídy potomků se v PHP tvoří pomocí klíčového slova extends. My použijeme třídu, která bude mít oproti předchozí třídě jednu vlastnost navíc - bude umět zpracovat pole nazvané zvyrazni_dny; v našem případě tedy dny prvního, sedmého, osmého, třináctého a šestadvacátého. Bude to vypadat nějak takhle:
<?
class lepsi_kalendar extends kalendar
{
var $zvyrazni_dny;
//atd.
}
?>
Kde se v našem kalendáři tvoří obsahy jednotlivých buněk? Tvoří se v metodě Bunka(). A právě tuto metodu bude naše nová třída implementovat lepším způsobem než ta původní. Půjde se na to tak, že se prozkoumá pole $zvyrazni_dny, a jestliže se v něm najde číslo, které chceme právě vepsat do buňky, napíše se větším písmem a tučně. Pavel Kácha v seriálu o HTML nám vysvětlil jak na to, takže to bude maličkost. V následujícím kódu si všimněte, jak jednoduše se dceřiné třídy píší:
<?
class lepsi_kalendar extends kalendar
{
var $zvyrazni_dny;
function Bunka ($radek, $sloupec, $PrvniDen, $PocetDnu)
{
$dny=Array(1=>"Po", "Út", "St", "Čt", "Pá", "So", "Ne");
if ($sloupec==1) return $dny[$radek];
$chcivratit
= ($sloupec-2)*7 + $radek - $PrvniDen+1;
if ($chcivratit<1 || $chcivratit>$PocetDnu) return " ";
else
{
if (in_array($chcivratit, $this->zvyrazni_dny))
return "<B><BIG>".$chcivratit."</BIG></B>";
else return $chcivratit;
}
}
}
$muj_kalendar= new lepsi_kalendar;
$muj_kalendar->mesic=7;
$muj_kalendar->rok=2004;
$muj_kalendar->zvyrazni_dny = Array(1,7,8,13,26);
$muj_kalendar->vypis();
?>
Ukázat skript | Spustit skript
Kód jako takový si vyžadá jeden komentář a tím je použití funkce
in_array,
o níž jsme zatím nemluvili. Je to na pochopení jednoduchá
funkce - vrátí TRUE, pokud je daná hodnota (v našem případě
$chcivratit) v daném poli (v našem případě $this->zvyrazni_dny).
Pokud tam ten den je, vrátíme jako obsah buňky zvýrazněný text, pokud
ne, vrátíme text normální.
Daleko zajímavější je, jak funguje celý skript. Protože třída
lepsi_kalendar rozšiřuje třídu kalendar, dědí z této rodičovské třídy
všechno, co sama nedělá jinak. Tak například dědí vlastnosti mesic a rok, a dědí rovněž metodu vypis. Co nedědí je metoda Bunka, protože tu si upravuje k
obrazu svému. Je tedy jasné, že děděním můžeme získat řadu tříd, které
rozšiřují možnosti nějaké základní třídy.
To, co jsme uvedli nejsou všechny možnosti, které PHP pro práci s
objekty nabízí. Například existuje sada funkcí pro práci s objekty
a několik dalších možností při jejich vytváření. Co bychom ale
určitě vědět měli je skutečnost, že práce s objekty v PHP přináší svá
úskalí.
PHP nemá privátní metody.
To znamená, že v našem případě například neexistuje způsob, jak
zabránit tomu, aby se dala zavolat metoda Bunka zvnějšku třídy, ačkoli je to
metoda prospěšná pouze třídě jako takové a okolní svět by o ní vůbec
nemusel vědět. Odborně se principu, kdy je implementace metody ukryta
říká zapouzdření.
PHP zbaští nedeklarované atributy.
To může být hotová katastrofa.
Následující kód například bohužel bude fungovat přesto, že
stupidni_trida atribut $b vůbec nedeklaruje:
<?
class stupidni_trida
{
var $a;
}
$moje_trida=new
stupidni_trida;
$moje_trida->b=3;
echo $moje_trida->b;
?>
V PHP je neintuitivní přiřazování objektů. Co myslíte, že bude výsledkem následujícího skriptu?
<?
class stupidni_trida
{
var $a;
}
$prvni_trida=new
stupidni_trida;
$prvni_trida->a=1;
$druha_trida=$prvni_trida;
$druha_trida->a=2;
echo $prvni_trida->a; // není 2 ale 1
?>
Rovnítko (bohužel) nezpůsobí vytvoření odkazu na objekt, ale
vytvoření kopie objektu. Na to je třeba myslet.
Zda a jak budete v PHP používat objekty je samozřejmě na Vás. Níže
je ješě několik věcí a postřehů k objektům a PHP, které byste měli znát:
V dalším díle našeho seriálu opustíme OOP a podíváme se, jaké možnosti máme v PHP pro rozdělování zdrojových kódů do více fyzických souborů a jejich načítání.