9. diel - Statika v PHP
V predchádzajúcom cvičení, Riešené úlohy k 7.-8. lekciu OOP v PHP, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.
V minulej lekcii, Riešené úlohy k 7.-8. lekciu OOP v PHP , sme si vysvetlili ako funguje polymorfizmus a naučili sa používať autoloader pre automatické načítanie tried. V dnešnom PHP tutoriálu sa zoznámime s veľmi kontroverzné technikou - statikou.
POZOR! Dnešné lekcie vám ukáže statiku, teda postupy,
ktoré v podstate narušujú objektový model. OOP je obsahuje len pre
špeciálne prípady a všeobecne platí, že všetko ide napísať bez
statiky. Vždy musíme starostlivo zvážiť, či statiku
naozaj nutne potrebujeme. Všeobecne by som odporúčal statiku
vôbec nepoužívať, ak si nie ste úplne istí, čo robíte.
Podobne, ako globálne premenné je statika v objektovom programovaní niečo,
čo umožňuje písať zlý kód a porušovať dobré praktiky. Znalosti
použite s rozvahou, na svete bude potom menej zla.
Triedny prvky
V objektovo orientovanom programovaní sme už trochu zbehli a preto vieme, že aplikácia je zložená z množiny komunikujúcich objektov. Objekty sú vždy inštancie, vytvorené podľa nejakej triedy. Každá inštancia je unikátny a má svoj vnútorný stav (atribúty) a schopnosti (metódy).
Objektovo orientované programovanie však okrem inštančných prvkov umožňuje definovať aj prvky triedny. Jedná sa o atribúty a metódy, ktoré nepatria inštanciu, ale patrí triede. Triedny metódu teda voláme na triede, miesto na inštanciu a inštanciu vôbec nepotrebujeme. Takúto metódu označíme kľúčovým slovom static a môžeme ju zavolať odkiaľkoľvek z programu bez toho aby sme mali inštanciu. Skúsme si to na jednoduchom príklade.
Matematická trieda
Vytvorme si v zložke "tridy" novú triedu Matematika.php. Do nej najprv umiestnime inštančný metódu na druhú (), ako sme boli zvyknutí doteraz:
class Matematika { public function naDruhou($zaklad) { return $zaklad *$zaklad; } }
V index.php si skúsme nechať vypočítať druhú mocninu pomocou našej metódy. Vytvoríme si inštanciu našej triedy Matematika a zavoláme na nej príslušnú metódu:
{PHP} require_once('tridy/Matematika.php'); $matematika = new Matematika(); echo($matematika->naDruhou(12));
{PHP} class Matematika { public function naDruhou($zaklad) { return $zaklad *$zaklad; } }
Výstupom programu je samozrejme číslo 144, ale o ten tu teraz nejde. Predstavte si, že v nejakej výpočtovej aplikácii používate na mnohých miestach v mnohých triedach nejaké podobné pomocné výpočty. Bolo by trochu nepraktické stále tvoriť nové inštancie alebo si odovzdávať inštanciu triedy Matematika. Z toho dôvodu urobíme metódu na druhú () statickú. Upravme triedu Matematika na túto podobu:
class Matematika { public static function naDruhou($zaklad) { return $zaklad *$zaklad; } }
V index.php odstránime vytvorenie inštancie a metódu na druhú () budeme volať priamo na triede Matematika. K volanie triednych prvkov nepoužívame operátor šípky (->), ale čtyřtečku (: :
{PHP} require_once('tridy/Matematika.php'); echo(Matematika::naDruhou(12));
{PHP} class Matematika { public static function naDruhou($zaklad) { return $zaklad *$zaklad; } }
Metódu sme zavolali bez inštancie. Dá sa povedať, že je tiež globálna a viditeľná odkiaľkoľvek, čo môže pri zlom použití spôsobiť veľmi zlú čitateľnosť kódu (viď ďalej). Vieme, že OOP sa snažia skôr čo najviac vecí skrývať. V tomto prípade je to však v poriadku a ďalej v seriáli si vysvetlíme ďalšie správna i zlá použitie.
Kombinácia statických a inštančných prvkov
Trieda nemusí obsahovať len inštančný alebo len statické prvky, ale môže obsahovať ich kombináciu. Inštančný prvky sú potom prístupné len na inštanciu, statické zase len na triede.
Číslovanie inštancií
O statických prvkoch môžeme zjednodušene povedať, že sú spoločné pre všetky inštancie, pretože patrí tej jednej triede. Vráťme sa zas k našim ľuďom a dajme tomu, že ich budeme potrebovať číslovať. Každý človek bude mať atribút $ id, v ktorom bude unikátne číslo. Prvý vytvorený človek bude mať $ id = 1, druhý $ id = 2 a tak ďalej. Kde ale uchovávať koľko ľudí sme už vytvorili?
Ak poznáme statiku, nie je nič jednoduchšie ako pridať do triedy Clovek statický atribút pocetLidi, nastavený na 0. Trieda si teda pamätá koľko ľudí bolo vytvorené. Je to aj logicky správne, pretože atribút je zdieľaný medzi všetkými inštanciami a preto je na triede. V konstruktoru človeka potom tento statický atribút vždy zvýšime o 1 a do inštančný premennej $ id dosadíme toto číslo.
Trieda Clovek.php bude vyzerať s touto malou úpravou nasledovne:
class Clovek { public $jmeno; public $prijmeni; public $vek; private $unava = 0; public $id; private static $pocetLidi = 0; public function __construct($jmeno, $prijmeni, $vek) { $this->jmeno = $jmeno; $this->prijmeni = $prijmeni; $this->vek = $vek; self::$pocetLidi++; $this->id = self::$pocetLidi; } public function spi($doba) { $this->unava -= $doba * 10; if ($this->unava < 0) $this->unava = 0; } public function behej($vzdalenost) { if ($this->unava + $vzdalenost <= 20) $this->unava += $vzdalenost; else echo('Jsem příliš unavený.'); } public function pozdrav() { echo('Ahoj, já jsem ' . $this->jmeno); } protected function celeJmeno() { return $this->jmeno . ' ' . $this->prijmeni; } public function __toString() { return $this->jmeno . ' - ' . $this->id; } }
Pri bližšom pohľade vidíme 2 nové atribúty, inštančný $ id a triedny $ pocetLidi.
V konstruktoru inkrementuje (zvýšime o 1) premennú $ pocetLidi a hodnotu dosadíme nové inštanciu do jej $ id. Ku statickým prvkom sa vnútri triedy pristupuje pomocou kľúčového slova self. Má podobný význam ako $ this, ktoré uchovávalo aktuálne inštanciu, self uchováva aktuálne triedu. Mätúce môže byť, že sa za čtyřtečku na rozdiel od $ this píše dolár.
Posledná zmena spočíva v metóde __toString (), kde vraciame aj ID, aby sme jednoducho videli, že nám ich prideľovanie funguje.
V index.php poupravíme cyklus tak, aby namiesto zdravenie ľudí vypisoval. Pre úplnosť dodávam aj ich tvorenia:
{PHP} require_once('tridy/Clovek.php'); require_once('tridy/Javista.php'); $lide = array(); $lide[] = new Clovek('Karel', 'Novák', 30); $lide[] = new Javista('Jan', 'Nový', 24, 'Eclipse'); $lide[] = new Clovek('Josef', 'Nový', 50); $lide[] = new Javista('Tomáš', 'Marný', 28, 'NetBeans'); $lide[] = new Clovek('Marie', 'Nová', 32); foreach ($lide as $clovek) { echo($clovek . '<br />'); }
{PHP} class Clovek { public $jmeno; public $prijmeni; public $vek; private $unava = 0; public $id; private static $pocetLidi = 0; public function __construct($jmeno, $prijmeni, $vek) { $this->jmeno = $jmeno; $this->prijmeni = $prijmeni; $this->vek = $vek; self::$pocetLidi++; $this->id = self::$pocetLidi; } public function spi($doba) { $this->unava -= $doba * 10; if ($this->unava < 0) $this->unava = 0; } public function behej($vzdalenost) { if ($this->unava + $vzdalenost <= 20) $this->unava += $vzdalenost; else echo('Jsem příliš unavený.'); } public function pozdrav() { echo('Ahoj, já jsem ' . $this->jmeno); } protected function celeJmeno() { return $this->jmeno . ' ' . $this->prijmeni; } public function __toString() { return $this->jmeno . ' - ' . $this->id; } }
{PHP} class Javista extends Clovek { public $ide; public function __construct($jmeno, $prijmeni, $vek, $ide) { $this->ide = $ide; parent::__construct($jmeno, $prijmeni, $vek); } public function programuj() { echo("Programuji v {$this->ide}..."); } public function pozdrav() { echo('Hello world! Jsem ' . $this->jmeno); } }
Výstup programu:
Vidíme, že statický atribút $ pocetLidi naozaj náleží triede Clovek. Keď PHP triedu prvýkrát načíta, vytvorí atribút a nastaví do neho hodnotu 0. Statický atribút na triede Clovek v pamäti pretrváva do skončenia skriptu bez ohľadu na to, či existujú nejaké inštancie ľudí alebo nie. S jeho hodnotou môžeme manipulovať z inštančných metód (tu z konstruktoru). Zo statickej metódy nemožno volať metóda inštančný, pretože k tomu potrebujeme inštancii Naopak to teda nedá.
Bez statiky by sa tento príklad riešil pomocou objektu, ktorý by ľudí vyrábal. Takým objektom sa hovorí továrne, ale o tom zas niekedy inokedy.
Statika je veľmi dôležitá, veľmi používaná a často veľmi mylne chápaná programátorská technika. Z toho dôvodu ju budú venované ešte 2 nasledujúce lekcie. Povieme si kedy ju používať a kedy nie. Budete na ňu narážať často a je veľmi dôležité, aby ste chápali ako funguje. V budúcej lekcii, Triedny prvky v PHP druhýkrát - konštanty , budeme pokračovať a vysvetlíme si ako sa v PHP používajú konštanty. Súbory z dnešnej lekcie sú ako vždy k stiahnutiu v archíve nižšie.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 589x (3.84 kB)
Aplikácia je vrátane zdrojových kódov v jazyku PHP