4. diel - Zapuzdrenie v PHP
V predchádzajúcom cvičení, Riešené úlohy k 1.-3. lekciu OOP v PHP, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.
V minulej lekcii, Riešené úlohy k 1.-3. lekciu OOP v PHP , sme si vysvetlili atribúty a základné magické metódy. Dnes si v tutoriálu povieme niečo o zapuzdrenie v PHP.
Zapuzdrenie
OOP stojí na troch základných pilieroch: Zapuzdrenie, Dedičnosti a polymorfizmu. Prvý z nich si dnes preberieme.
Zapuzdrenie umožňuje skryť niektoré metódy a atribúty tak, aby zostali použiteľné len pre triedu zvnútra. Objekt si môžeme predstaviť ako čiernu skrinku (anglicky blackbox), ktorá má určité rozhranie (interface), cez ktoré jej odovzdávame inštrukcie / dáta a ona je spracováva.
Nevieme, ako to vo vnútri funguje, ale vieme, ako sa navonok chová a používa. Nemôžeme teda spôsobiť nejakú chybu, pretože využívame a vidíme len to, čo tvorca triedy sprístupnil.
U našej triedy človek by mohol byť problém vo chvíli, keď by mala mať atribút $ datumNarozeni a na jeho základe ďalšie atribúty: $ plnoletý a $ spevokol. Keby niekto objektu zvonku zmenil $ datumNarozeni, prestali by platiť premenné plnoletý a spevokol. Hovoríme, že vnútorný stav objektu by bol nekonzistentné. Toto sa nám v štruktúrovanom programovaní môže pokojne stáť. V OOP však objekt zapouzdříme a atribút $ datumNarozeni označíme ako privátne, zvonka teda nebude viditeľný. Naopak von vystavíme metódu zmenDatumNarozeni (), ktorá dosadí nové dátum narodenia do premennej datumNarozeni a zároveň vykoná potrebný prepočet veku a prehodnotenie plnoletosti. Použitie objektu je bezpečné a aplikácia stabilné.
Zapuzdrenie teda donúti programátorov používať objekt len tým správnym spôsobom. Rozhranie (interface) triedy rozdelí na verejne prístupné (public) a vnútornú štruktúru (private).
Všeobecne býva snaha skryť toho v objekte čo najviac a zvonka sprístupniť len to dôležité. Do dátumu narodenia sa u našich ľudí púšťať nebudeme, keďže výpočet veku nie je úplne triviálne.
Spánok
Privátne atribúty slúži teda objektom na spracovávanie nejakej ich vnútornej logiky, ktorá zvonku nie je vidieť a nemôžeme do nej zasahovať. Do funkcie ľudí iste patrí spánok a poslúži teda ako dokonalý ukážkový príklad.
Človek bude mať nejakú únavu, ktorá bude uložená v privátnom atribúte $ unava.
Ďalej bude mať metódu spi (), ktorá bude brať v parametri počet hodín, ktoré má človek naspat. Metóda spi () zníži únavu podľa toho, koľko hodín človek naponáhlo. Samozrejme nezabudneme ošetriť, aby nebola únava záporná keď sa niekto pokúsi naspat viac hodín, než je možné.
Aby bolo možné človeka aj unaviť, dáme mu metódu behajte (), ktorá bude v parametri brať počet kilometrov. Pre jednoduchosť si metódu Naprogramujte tak, aby za každý kilometer pripísala 1 jednotku únavy. Ak je únava príliš vysoká, metóda vypíše, že už behať nedá.
Trieda Clovek s novou funkcionalitou bude vyzerať asi takto:
class Clovek { public $jmeno; public $prijmeni; public $vek; private $unava = 0; public function __construct($jmeno, $prijmeni, $vek) { $this->jmeno = $jmeno; $this->prijmeni = $prijmeni; $this->vek = $vek; } 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); } public function __toString() { return $this->jmeno; } }
Všimnite si, že sme atribútu únava pri jeho deklarácii rovno nastaviť hodnotu 0. Táto hodnota sa nastaví každej inštancii pri jej vytvorení a je to teda alternatíva k tomu, keby sme priradenie nuly napísali do konstruktoru.
Inak na triede nie je okrem privátneho modifikátora prístupe u atribútu $ unava nič, čo by sme už nevideli. Metóda behajte () nie je príliš elegantný, pretože v prípade veľkej únavy (viac ako 20 jednotiek) priamo vypisuje hlášku, že je človek príliš unavený. To znižuje univerzálnosť objektu, pretože takýto výpis nemusíme vždy chcieť. Pre naše účely je to však teraz ideálne a počas seriálu si ukážeme ako sa chybové stavy objektov správne rieši.
Zvonku objektu nie je možné meniť únavu inak, než unavením človeka pomocou metódy behajte () alebo necháním človeka vyspať. Teda tak, ako sme to my, autori triedy, navrhli. Objekt nemožno rozbiť alebo použiť zle.
Presuňme sa do index.php a novú funkcionalitu si otestujte. Môžeme vymazať volanie pozdravovania na oboch našich inštanciách a jednu z nich nechajme ubehnúť 3x 10km:
{PHP} require_once('tridy/Clovek.php'); $karel = new Clovek('Karel', 'Novák', 30); $jan = new Clovek('Jan', 'Nový', 24); $karel->behej(10); $karel->behej(10); $karel->behej(10); {/PHP}
{PHP} // Obsah souboru Clovek.php class Clovek { public $jmeno; public $prijmeni; public $vek; private $unava = 0; public function __construct($jmeno, $prijmeni, $vek) { $this->jmeno = $jmeno; $this->prijmeni = $prijmeni; $this->vek = $vek; } 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); } public function __toString() { return $this->jmeno; } } {/PHP}
Výstup programu je:
Karel ubehol 2x 10km a potom dosiahol stanovené hranice únavy, ktorú sme zvolili na 20 jednotiek. Ďalší pokus o beh sa teda už nepodaril a program raz vypísal, že je príliš unavený.
Dodajme do programu spánok, na 10km vzdialenosti sme v kóde zvolili 1 hodinu spánku. Dodajme teda túto hodinu pred posledných 10km:
{PHP} require_once('tridy/Clovek.php'); $karel = new Clovek('Karel', 'Novák', 30); $jan = new Clovek('Jan', 'Nový', 24); $karel->behej(10); $karel->behej(10); $karel->spi(1); $karel->behej(10); {/PHP}
{PHP} class Clovek { public $jmeno; public $prijmeni; public $vek; private $unava = 0; public function __construct($jmeno, $prijmeni, $vek) { $this->jmeno = $jmeno; $this->prijmeni = $prijmeni; $this->vek = $vek; } 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); } public function __toString() { return $this->jmeno; } }
Chybová hláška teraz zmizla a všetko prebehlo v poriadku.
Keď sa pokúsime zvonku (z ktoréhokoľvek iného súboru, než je Clovek.php) pristúpiť k privátnemu atribútu $ unava, dostaneme vyhubováno:
$karel->unava = 0;
Privátne metódy
Privátne môžu byť samozrejme nielen atribúty, ale aj metódy, ktoré vykonávajú nejakú funkcionalitu pre vnútornú potrebu triedy. Často sa používajú aj v prípade, keď máme príliš zložitú verejnú metódu. V tej chvíli ju rozdelíme na niekoľko privátnych metód, ktoré verejná metóda volá. Počet riadkov v metóde by ideálne nemal presiahnuť asi 30, počet riadkov na triedu asi 500. Teraz je to jedno, u väčších projektov a tried je dobré sa tým riadiť a v prípade veľkého rozsahu jednoducho funkcionalitu rozdeliť do viacerých komponentov, ktoré spolu budú spolupracovať. Len tak dokážeme udržať našu aplikáciu čitateľnú a ďalej rozšíriteľnú.
Aplikáciu máte ako vždy nižšie k stiahnutiu. V budúcej lekcii, Prvý objektová komponenta v PHP - Galéria obrázkov , si urobíme krátku odbočku od našich ľudí a vytvoríme si prvé komponent, ktorá bude mať reálne použitie. Pôjde o galériu obrázkov.
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é 805x (1.97 kB)
Aplikácia je vrátane zdrojových kódov v jazyku PHP