4. díl - Zapouzdření v PHP

PHP Objektově orientované programování Zapouzdření v PHP American English version English version

V minulém dílu našeho seriálu tutoriálů o objektově orientovaném programování v PHP jsme si vysvětlili atributy a základní magické metody. Dnes si povíme něco o zapouzdření.

Zapouzdření

OOP stojí na třech základních pilířích: Zapouzdření, Dědičnosti a Polymorfismu. První z nich si dnes probereme.

Zapouzdření umožňuje skrýt některé metody a atributy tak, aby zůstaly použitelné jen pro třídu zevnitř. Objekt si můžeme představit jako černou skřínku (anglicky blackbox), která má určité rozhraní (interface), přes které jí předáváme instrukce/data a ona je zpracovává.

Nevíme, jak to uvnitř funguje, ale víme, jak se navenek chová a používá. Nemůžeme tedy způsobit nějakou chybu, protože využíváme a vidíme jen to, co tvůrce třídy zpřístupnil.

U naší třídy člověk by mohl být problém ve chvíli, když by měla mít atribut $datumNarozeni a na jeho základě další atributy: $plnolety a $vek. Kdyby někdo objektu zvenčí změnil $datumNarozeni, přestaly by platit proměnné plnolety a vek. Říkáme, že vnitřní stav objektu by byl nekonzistentní. Toto se nám ve strukturovaném programování může klidně stát. V OOP však objekt zapouzdříme a atribut $datumNarozeni označíme jako privátní, zvenčí tedy nebude viditelný. Naopak ven vystavíme metodu zmenDatumNaro­zeni(), která dosadí nové datum narození do proměnné datumNarozeni a zároveň provede potřebný přepočet věku a přehodnocení plnoletosti. Použití objektu je bezpečné a aplikace stabilní.

Zapouzdření tedy donutí programátory používat objekt jen tím správným způsobem. Rozhraní (interface) třídy rozdělí na veřejně přístupné (public) a vnitřní strukturu (private).

Obecně bývá snaha skrýt toho v objektu co nejvíce a zvenčí zpřístupnit jen to důležité. Do data narození se u našich lidí pouštět nebudeme, jelikož výpočet věku není úplně triviální.

Spánek

Privátní atributy slouží tedy objektům ke zpracovávání nějaké jejich vnitřní logiky, která zvenčí není vidět a nemůžeme do ní zasahovat. Do funkce lidí jistě spadá spánek a poslouží tedy jako dokonalý ukázkový příklad.

Člověk bude mít nějakou únavu, která bude uložená v privátním atributu $unava.

Dále bude mít metodu spi(), která bude brát v parametru počet hodin, které má člověk naspat. Metoda spi() sníží únavu podle toho, kolik hodin člověk naspí. Samozřejmě nezapomeneme ošetřit, aby nebyla únava záporná když se někdo pokusí naspat více hodin, než je možné.

Aby bylo možné člověka i unavit, dáme mu metodu behej(), která bude v parametru brát počet kilometrů. Pro jednoduchost si metodu naprogramujme tak, aby za každý kilometr přičetla 1 jednotku únavy. Pokud je únava příliš vysoká, metoda vypíše, že již běhat nelze.

Třída Clovek s novou funkcionalitou bude vypadat 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šimněte si, že jsme atributu únava při jeho deklaraci rovnou nastavili hodnotu 0. Tato hodnota se nastaví každé instanci při jejím vytvoření a je to tedy alternativa k tomu, kdybychom přiřazení nuly napsali do konstruktoru.

Jinak na třídě není kromě privátního modifikátoru přístupu u atributu $unava nic, co bychom již neviděli. Metoda behej() není příliš elegantní, jelikož v případě velké únavy (vyšší než 20 jednotek) přímo vypisuje hlášku, že je člověk příliš unavený. To snižuje univerzálnost objektu, jelikož takový výpis nemusíme vždy chtít. Pro naše účely je to však nyní ideální a během seriálu si ukážeme jak se chybové stavy objektů správně řeší.

Zvenku objektu není možné měnit únavu jinak, než unavením člověka pomocí metody behej() nebo necháním člověka vyspat. Tedy tak, jak jsme to my, autoři třídy, navrhli. Objekt nelze rozbít nebo použít špatně.

Přesuňme se do index.php a novou funkcionalitu si otestujme. Můžeme vymazat volání zdravení na obou našich instancích a jednu z nich nechme uběhnout 3x 10km:

$karel->behej(10);
$karel->behej(10);
$karel->behej(10);

Výstup programu je:

Zpouzdření v PHP

Karel uběhl 2x 10km a poté dosáhl stanovené hranice únavy, kterou jsme zvolili na 20 jednotek. Další pokus o běh se tedy již nezdařil a program jednou vypsal, že je příliš unavený.

Dodejme do programu spánek, na 10km vzdálenosti jsme v kódu zvolili 1 hodinu spánku. Dodejme tedy tuto hodinu před posledních 10km:

$karel->behej(10);
$karel->behej(10);
$karel->spi(1);
$karel->behej(10);

Chybová hláška nyní zmizela a vše proběhlo v pořádku.

Když se pokusíme zvenčí (z kteréhokoli jiného souboru, než je Clovek.php) přistoupit k privátnímu atributu $unava, dostaneme vyhubováno:

$karel->unava = 0;
Zpouzdření v PHP

Privátní metody

Privátní mohou být samozřejmě nejen atributy, ale i metody, které vykonávají nějakou funkcionalitu pro vnitřní potřebu třídy. Často se používají také v případě, když máme příliš složitou veřejnou metodu. V tu chvíli ji rozdělíme na několik privátních metod, které veřejná metoda volá. Počet řádků v metodě by ideálně neměl přesáhnout asi 30, počet řádků na třídu asi 500. Nyní je to jedno, u větších projektů a tříd je dobré se tím řídit a v případě velkého rozsahu jednoduše funkcionalitu rozdělit do více komponent, které spolu budou spolupracovat. Jen tak dokážeme udržet naši aplikaci čitelnou a dále rozšiřitelnou.

Aplikaci máte jako vždy níže ke stažení. Příště si uděláme krátkou odbočku od našich lidí a vytvoříme si první komponentu, která bude mít reálné použití. Půjde o galerii obrázků.


 

Stáhnout

Staženo 459x (877 B)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

  Aktivity (2)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (19 hlasů) :
4.894734.894734.894734.894734.89473


 



 

 

Komentáře
Zobrazit starší komentáře (29)

Avatar
Michael Olšavský:

Dnes jsem v jedné Unity3D knihovne narazil na třídu s 3500 řádky kódu. Je to sice napsané v C#, takže to není přímé porovnání, qle je to síla.

 
Odpovědět 17.11.2013 22:29
Avatar
timkovic
Člen
Avatar
timkovic:

Ahojte, co znamena += napr. v tomto: $this->unava += $vzdalenost;? Vdaka

 
Odpovědět 31.10.2014 18:55
Avatar
Tukmak
Člen
Avatar
Odpovídá na timkovic
Tukmak:

To je zkrácený zápis pro

$this->unava = $this->unava + $vzdalenost;
 
Odpovědět  +2 31.10.2014 19:00
Avatar
Tomáš123
Člen
Avatar
Tomáš123:

Ahoj, chcel by som sa opýtať, prečo je v kóde pre triedu Clovek definované
public $jmeno;
public $prijmeni;
public $vek;

... a hneď potom funkcia kde sa odkazuje na:
$this->jmeno = $jmeno;
$this->prijmeni = $prijmeni;
$this->vek = $vek;

Aký je medzi tým rozdiel? Prvá časť nám sprístupňuje hodnoty mena, priezviska a veku a druhá nám umožňuje zadať ich pri definovaní novej metódy človeka?

Ďakujem

Odpovědět 23.2.2015 20:37
Keby nebolo Internetu Exploreru, nebolo by dnešného internetu.
Avatar
IT Man
Redaktor
Avatar
Odpovídá na Tomáš123
IT Man:

U toho prvního definujeme proměnné. U konstruktoru přiřazujeme do těchto proměnných hodnoty. :)

Odpovědět  +4 23.2.2015 20:43
Když nevíš jak dál, podá ti ruku někdo, od koho by jsi to nečekal. A tu šanci musíš přijmout!
Avatar
aghtczst
Člen
Avatar
Odpovídá na IT Man
aghtczst:

Edit: Nevermind

Editováno 24.6.2015 16:26
 
Odpovědět  -1 24.6.2015 16:23
Avatar
Odpovídá na aghtczst
Martin Konečný (pavelco1998):

Objekt má nějaké atributy (public $meno, $vek, $krajina). Ty defaultně ale nemají žádnou hodnotu, proto je předáš metodě __construct (ta se zavolá při vytvoření objektu), která ty hodnoty uloží.

Proměnná $this znamená daný objekt, takže ta metoda __construct() nastaví hodnoty svým atributům $meno, $vek a $krajina

 
Odpovědět 24.6.2015 16:27
Avatar
loading84
Člen
Avatar
loading84:
<?php

 class Clovek

 {

  public $jmeno;
  public $prijmeni;
  public $vek;
  private $energie=0;

  public function __construct($jmeno, $prijmeni, $vek)

              {
              $this->jmeno = $jmeno;
              $this->prijmeni = $prijmeni;
              $this->vek =$vek;
              }

  public function spi($doba)
                 {
                 $this->energie=$this->energie+($doba*10);

                 }

  public function behej($vzdalenost)
                  {
                   $this->energie=$this->energie-$vzdalenost;



                  if($this->energie>0)

                         echo('Ubehl jsem to');
                         else echo('Jsem prilis unaveny.');



                  }


  public function pozdrav()
              {
              echo('Ahoj, já jsem ' .$this->jmeno .' '.$this->prijmeni.' a je mi '.$this->vek.' let.');
              }

  public function __toString()

                   {
                   return $this->jmeno;
                   }

  /*
  public function __destruct()
                  {
                  echo('Byl jsem odstranen z pameti');
                  }
 */
 }



 ?>

Jsem si s tim pohral trochu jinak. .-)

 
Odpovědět 10.10.2015 20:55
Avatar
Odpovídá na loading84
Martin Konečný (pavelco1998):

Jen v metodě běhej se ti může trochu rozházet energie. I přes to, že je člověk unavený, pořád se mu sníží energie, takže pak může být i v minusu :)

 
Odpovědět 10.10.2015 21:16
Avatar
loading84
Člen
Avatar
Odpovídá na Martin Konečný (pavelco1998)
loading84:

Já tomu rozumím. Ale pro ilustraci mi to stačí. Když v podstatě jdou kilometry do mínusu tak říká že je unavený. Prostě přepočítává energii jestli to uběhne nebo ne.

 
Odpovědět 11.10.2015 10:24
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 39. Zobrazit vše