Hlavní navigace

PHP v objetí objektů (4)

Michal Burda

Dnes si podrobně probereme význam konstrukce NazevTridy::NazevMetody(). Čeká nás i zmínka o polymorfizmu.

Statická volání metod

V této chvíli se nemůžu nezmínit o obecném významu konstrukce ( NazevTridy::nazevMetody()). Význam tohoto příkazu závisí tom, v jakém kontextu je proveden.

Je-li příkaz proveden vně jakékoliv metody, znamená to statické volání metody, tj. provedení metody třídy bez návaznosti na nějaký konkrétní objekt. Například takovýto kód PHP je úplně v pořádku (pro inspiraci jsem si odskočil do API Javy):

<?
class Math {
  function sin($arg) {
    return sin($arg);
  }

  #...
}

/*
K statickému volání metody sin() třídy Math
nepotřebujeme vytvářet žádný objekt této třídy:
*/
print Math::sin(0);
?> 

Staticky volaná metoda se chová jako obyčejná funkce. Otázkou může být, jak se bude nakládat s proměnnou $this  – úplně normálně. Po statickém zavolání metody je $this nedefinovaná lokální proměnná, která se po opuštění metody, stejně jako ostatní lokální proměnné, zruší. Jakákoliv práce s $this (např. $this->atribut = 'hodnota';) má platnost jen uvnitř metody a pochopitelně se nepromítne do žádného existujícího objektu.

Trochu jiná situace nastane, zavoláte-li takto nějakou metodu uvnitř jiné metody konkrétního objektu. Potom proměnná $this obsahuje náš objekt a volaná metoda jej může jakkoliv modifikovat. Ošidné je to, že volaná metoda může být úplně z jiné třídy, která třeba není v žádném příbuzenském vztahu s třídou vašeho objektu. Posuďte následující příklad.

class TridaA {
  var $promenna = '';

  function inicializuj() {
    $this->promenna = 'hodnota';
  }

  function delejNeco() {
    print 'Jsem v metodě třídy TridaA<BR>';
    $this->inicializuj();
    print $this->promenna;
  }
}

class TridaB {
  function delejNecoJineho() {
    print 'Jsem v metodě třídy TridaB<BR>';
    TridaA::delejNeco();
  }
}

$objekt_b = new TridaB;
$objekt_b->delejNecoJineho(); 

A tady je výstup:

Jsem v metodě třídy TridaB
Jsem v metodě třídy TridaA

Fatal error: Call to undefined function:
inicializuj() in /var/www/priklad.php on line 

Co je špatně? Vytváříme objekt třídy TridaB a voláme jeho metodu delejNecoJineho(). Tato metoda vypíše hlášení a staticky (?) zavolá metodu delejNeco() třídy TridaA. Také tato metoda vypíše svůj text. Protože jsme ji však volali zevnitř jiné metody konkrétního objektu ( $objekt_b), je v její proměnné $this uložen odkaz na něj. Pak ale musí volání $this->inicializuj() nutně zkolabovat, protože objekt v $this patří k třídě TridaB, a ta žádnou metodu s názvem inicializuj nedefinuje. Vidíte, jak může být celá záležitost nebezpečná.

Abyste se vyhnuli nepříjemným chybám, měli byste tuto konstrukci používat jen pro volání předefinované metody z metody předefinovávající.

Polymorfizmus

Polymorfizmus je další příjemnost zavedená objektově orientovaným programováním. Spočívá v tom, že používáte pojmenované akce (rozumějte volání metod) objektů, každý objekt má však činnost implementovanou podle svých potřeb. Možná to zní složitě, ale až si vše ukážeme na příkladu, poznáte, že o žádnou vědu nejde.

Vraťme se znovu k našemu Menu. Vymysleli jsme další rozšíření stávajících tříd – budeme vytvářet třídu PodrobneMenu, která ke každé položce menu přidá krátký popis a umístí ji do samostatného odstavce.

class PodrobneMenu extends CentrovaneMenu {
  var $popisy;

  # nový konstruktor
  function PodrobneMenu() {
    $this->CentrovaneMenu();
  }

  # vylepšená verze vloz()
  function vloz($nazev, $url, $popis = '') {
    CentrovaneMenu::vloz($nazev, $url);
    $this->popisy[] = $popis;
  }

  # předefinování zobrazení jedné položky
  function zobrazPolozku($x) {
    print '<P><A HREF="' . $this->adresy[$x]
       . '">' . $this->nazvy[$x] . '</A> - '
       . $this->popisy[$x] . '</P>';
  }
}

$podrobne_menu = new PodrobneMenu();
$podrobne_menu->centrovat();
$podrobne_menu->vloz('Úvod', 'index.html', 'Úvodní slovo autora');
$podrobne_menu->vloz('Jedna', '1.html', '1. kapitola');
$podrobne_menu->vloz('Dvě', '2.html', '2. kapitola'); 

Uvedený kód nové třídy nepoužívá žádné nové konstrukce – všechny prvky syntaxe jsme si už popsali. Kde se tedy skrývá ten polymorfizmus? Jeho účinek nalezneme v metodě zobraz() třídy Menu(). Tam se v cyklu for volá akce (metoda) $this->zobrazPolozku() a díky polymorfizmu se provede pokaždé její „nejčerstvější“ verze; v třídách Menu a CentrovaneMenu je to metoda Menu::zobrazPolozku(), ale v třídě PodrobneMenu je to její vlastní metoda PodrobneMenu::zobrazPolozku()  – každý objekt si akci daného jména implementuje podle svého.

V uvedeném postupu můžeme jít ještě dál. Můžeme si třeba nadefinovat další třídy pro tabulky, formuláře a ostatní prvky WWW stránek, a pro každou z nich naprogramovat její vlastní metodu zobraz(). Objekty pak můžeme skladovat v polích nebo ve speciálních objektech (kontejnerech) a díky polymorfizmu na ně v cyklu hromadně volat zobraz(), čímž si vynutíme pokaždé jinou (ale patřičnou) odezvu. Pilný čtenář si jistě všechno promyslí a vyzkouší.

Poznámka: Pojem polymorfizmu se v jazycích C++ nebo Pascalu objevuje ve spojitosti s tzv. virtuálními metodami. V PHP je celá situace snadnější: „virtuálními“ jsou jednoduše úplně všechny metody.

Pokračování příště…

Našli jste v článku chybu?

8. 2. 2012 23:02

NeMeJa (neregistrovaný)

Chtěl bych doplnit že nakonec musíme ještě zavolat
$podrobne_menu->zobraz(); => tudíž naše vypsání pro $podrobne_menu bude vypadat následovně:
$podrobne_menu = new PodrobneMenu();
$podrobne_menu->centrovat();
$podrobne_menu->vloz('Úvod', 'index.html', 'Úvodní slovo autora');
$podrobne_menu->vloz('Jedna', '1.html', '1. kapitola');
$podrobne_menu->vloz('Dvě', '2.html');
$podrobne_menu-> zobraz();








13. 8. 2001 12:50

Pavel Cahyna (neregistrovaný)

Dekuji mnohokrat!

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

120na80.cz: 5 nejčastějších mýtů o kondomech

5 nejčastějších mýtů o kondomech

Lupa.cz: Kdo pochopí vtip, může jít do ČT vyvíjet weby

Kdo pochopí vtip, může jít do ČT vyvíjet weby

Vitalia.cz: Taky věříte na pravidlo 5 sekund?

Taky věříte na pravidlo 5 sekund?

Podnikatel.cz: V restauraci bez cigaret? Sněmovna kývla

V restauraci bez cigaret? Sněmovna kývla

Podnikatel.cz: Udávání a účtenková loterie, hloupá komedie

Udávání a účtenková loterie, hloupá komedie

120na80.cz: Na ucho teplý, nebo studený obklad?

Na ucho teplý, nebo studený obklad?

Měšec.cz: Jak levně odeslat balík přímo z domu?

Jak levně odeslat balík přímo z domu?

Vitalia.cz: Mondelez stahuje rizikovou čokoládu Milka

Mondelez stahuje rizikovou čokoládu Milka

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

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

Jak vymáhat výživné zadarmo?

Podnikatel.cz: Snížení DPH na 15 % se netýká všech

Snížení DPH na 15 % se netýká všech

Vitalia.cz: Když přijdete o oko, přijdete na rok o řidičák

Když přijdete o oko, přijdete na rok o řidičák

Vitalia.cz: Jmenuje se Janina a žije bez cukru

Jmenuje se Janina a žije bez cukru

Měšec.cz: Air Bank zruší TOP3 garanci a zdražuje kurzy

Air Bank zruší TOP3 garanci a zdražuje kurzy

Vitalia.cz: Spor o mortadelu: podle Lidlu falšovaná nebyla

Spor o mortadelu: podle Lidlu falšovaná nebyla

Podnikatel.cz: Chaos u EET pokračuje. Jsou tu další návrhy

Chaos u EET pokračuje. Jsou tu další návrhy

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

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

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