Hlavní navigace

PHP v objetí objektů (3)

Michal Burda 30. 7. 2001

Dnes si vezmeme na mušku dědičnost tříd a její použití v PHP skriptech. Ukážeme si také, jak předefinovat zděděné metody a jak jejich původní verze v předefinovaných metodách volat.

Dědičnost

V této chvíli máme vytvořen objekt, který jakžtakž „chodí“. Naplno jsme si přitom vychutnali výhody zapouzdření výkonných rutin a dat (umístění dat i funkcí do jedné entity). Může se však stát, že nám naše Menu po čase přestane vyhovovat. Najednou zjistíme, že občas potřebujeme menu umisťovat doprostřed stránky, a tak bychom chtěli, aby se to provádělo automaticky. Původní Menu ale často používáme, a proto chceme, aby zůstalo takové, jaké je. Na řadu proto přichází další mocný nástroj objektově orientovaného programování, dědičnost.

(Tohle je trochu vykonstruovaný příklad. V žádném případě tím nechci říct, abyste kvůli každé prkotině, kterou chcete do objektů naimplementovat, vytvářeli nové třídy. V praxi by se to všechno docela určitě fláklo do původní třídy Menu.) 

Vyrobíme novou třídu jménem CentrovaneMenu, která převezme všechny dobré vlastnosti původního Menu a navíc přidá nějaké další:

class CentrovaneMenu extends Menu {
  var $centrovat = false;

  # novy konstruktor
  function CentrovaneMenu($polozky = array()) {
    $this->Menu($polozky);
  }

  # centrovat menu?
  function centrovat($centr = true) {
    $this->centrovat = $centr;
  }

  # ještě tomu něco chybí...
} 

V definici třídy nám přibylo další klíčové slůvko: extends. Za něj píšeme název třídy, ze které bude dědit (říká se jí parent class, rodičovská třída nebo ancestor, předek). PHP neumí mnohonásobnou dědičnost, takže každý objekt může mít nejvýše jednoho předka. Třída CentrovaneMenu dědí své vlastnosti z třídy Menu  – má všechny atributy a funkce stejné jako její rodičovská třída. Dodefinovali jsme navíc ještě jeden atribut, $centrovat, který určuje, má-li se menu vystředit.

Pro novou třídu jsme vytvořili také nový konstruktor. Nebylo to v zásadě nutné, protože konstruktor CentrovaneMenu() jenom volá zděděný konstruktor Menu(), ale myslím si, že je dobrým zvykem, ke každé třídě automaticky vytvářet konstruktor nový – s největší pravděpodobností jej dříve nebo později budete stejně potřebovat. (Všimněte si, že se zděděný konstruktor volá stejně jako jakákoliv obyčejná metoda.)

Třída CentrovaneMenu taková, jak ji máme nyní definovánu, bude samozřejmě plně funkční. Zdědila totiž všechny metody i atributy třídy Menu, takže se bude přesně jako Menu chovat. Nám zbývá doplnit metodu zobraz(), aby reagovala i na hodnotu atributu centrovat.

Předefinování metody

class CentrovaneMenu extends Menu {
  # atribut, konstruktor a metoda viz vyse...

  # predefinovana metoda zobraz
  function zobraz() {
    if ($this->centrovat) {
      print '<CENTER>';
    }
    Menu::zobraz();
    if ($this->centrovat) {
      print '</CENTER>';
    }
  }
} 

Co se stalo nyní? Předefinovali jsme metodu zobraz(). Ve třídě Menu byla metoda zobraz() již nějakým způsobem definována. Třída CentrovaneMenu její definici zdědila, ale jelikož nám plně nevyhovuje, uvedli jsme definici novou. Původní zobraz() byla dobrá až na malý nedostatek: necentrovala. Proto podle nové definice požadujeme, aby metoda nejprve podle hodnoty atributu centrovat vypsala tag <CENTER>, poté zavolala předefinovanou metodu zobraz() třídy Menu, a nakonec vypsala ukončovací tag  </CENTER>.

Všimněte si, jak se překrytá metoda zobraz() třídy Menu volala:

Menu::zobraz(); 

Obyčejný zápis

$this->zobraz(); 

nelze použít, protože by to znamenalo rekurzivní volání metody zobraz(). Muselo se proto přijít s novou syntaktickou konstrukcí: název třídy, operátor příslušnosti ( ::) a název metody. Podle takovéhoto zápisu už PHP pozná, kterou verzi metody zobraz() vlastně chcete volat.

Poznámka: Na tomto místě si dovoluji znovu poukázat na rozdíl mezi voláním zděděného konstruktoru ($this->RodicovskaTrida()) a voláním předefinované metody (NazevTridy::na­zevMetody()). Protože u konstruktorů nemůže dojít k omylu, používá se standardní volání metody.

Poznámka: Konstrukce NazevTridy::na­zevMetody() se dá využít i k zajištění toho, aby se vždy volala požadovaná verze metody, nicméně obvykle se to nedělá, protože si tak zavíráme vrátka k polymorfizmu (viz později).

Tolik pro dnešek o PHP a objektově orientovaném programování. Konstrukce NazevTridy::nazevMetody() se používá i k tzv. statickému volání metod. Podrobněji se tomu budeme věnovat v příštím dílu.

Našli jste v článku chybu?

14. 9. 2007 6:51

ATom (neregistrovaný)
Myslím, že místo Menu::zobraz(); by bylo daleko lepší použít parent::zobraz()

21. 2. 2007 13:05

Eddie (neregistrovaný)
Ako na viacnasobne dedenie metod tried. Priklad: mam triedy A B C D. Chcem aby trieda A zdedila vlastnosti tried B C a D ale nechcem to zapisovat ako A extends B, B extends C...

Podla clanku na zive.sk sa to da urobit pomocou interface-ov ale nepisu ako... Vie to niekto spravit?

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

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

Přehledná titulka, průvodci, responzivita

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Vitalia.cz: Nestlé vyvinula nový typ „netloustnoucího“ cukru

Nestlé vyvinula nový typ „netloustnoucího“ cukru

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

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

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

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

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

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

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

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

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

Podnikatelům dorazí varování od BSA

120na80.cz: Horní cesty dýchací. Zkuste fytofarmaka

Horní cesty dýchací. Zkuste fytofarmaka

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

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

Vitalia.cz: To není kašel! Správná diagnóza zachrání život

To není kašel! Správná diagnóza zachrání život

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

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

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

DigiZone.cz: ČT má dalšího zástupce v EBU

ČT má dalšího zástupce v EBU

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

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

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