NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!
NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.

Lekce 4 - Zapouzdření v PHP

V předešlém cvičení, Řešené úlohy k 1.-3. lekci OOP v PHP, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

Dnes si v tutoriálu povíme něco o zapouzdření v PHP.

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 Clovek 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 zmenDatumNarozeni(), 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 k aktuální hodnotě ú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
{
    private int $unava = 0;

    public function __construct(public string $jmeno, public string $prijmeni, public int $vek) {}

    public function spi(int $doba): void
    {
        $this->unava -= $doba * 10;
        if ($this->unava < 0)
            $this->unava = 0;
    }

    public function behej(int $vzdalenost): void
    {
        if ($this->unava + $vzdalenost <= 20)
            $this->unava += $vzdalenost;
        else
            echo('Jsem příliš unavený.');
    }

    public function pozdrav(): void
    {
        echo('Ahoj, já jsem ' . $this->jmeno);
    }

    public function __toString(): string
    {
        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 10 km:

$karel->behej(10);
$karel->behej(10);
$karel->behej(10);
// Obsah souboru Clovek.php
class Clovek
{
    private int $unava = 0;

    public function __construct(public string $jmeno, public string $prijmeni, public int $vek) {}

    public function spi(int $doba): void
    {
        $this->unava -= $doba * 10;
        if ($this->unava < 0)
            $this->unava = 0;
    }

    public function behej(int $vzdalenost): void
    {
        if ($this->unava + $vzdalenost <= 20)
            $this->unava += $vzdalenost;
        else
            echo('Jsem příliš unavený.');
    }

    public function pozdrav(): void
    {
        echo('Ahoj, já jsem ' . $this->jmeno);
    }

    public function __toString(): string
    {
        return $this->jmeno;
    }
}

Výstup programu je:

OOP na ITnetwork
localhost

Karel uběhl 2x 10 km 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 10 km vzdálenosti jsme v kódu zvolili 1 hodinu spánku. Dodejme tedy tuto hodinu před posledních 10 km:

$karel->behej(10);
$karel->behej(10);
$karel->spi(1);
$karel->behej(10);
class Clovek
{
    private int $unava = 0;

    public function __construct(public string $jmeno, public string $prijmeni, public int $vek) {}

    public function spi(int $doba): void
    {
        $this->unava -= $doba * 10;
        if ($this->unava < 0)
            $this->unava = 0;
    }

    public function behej(int $vzdalenost): void
    {
        if ($this->unava + $vzdalenost <= 20)
            $this->unava += $vzdalenost;
        else
            echo('Jsem příliš unavený.');
    }

    public function pozdrav(): void
    {
        echo('Ahoj, já jsem ' . $this->jmeno);
    }

    public function __toString(): string
    {
        return $this->jmeno;
    }

}

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;

Příslušné chybové hlášení:

OOP na ITnetwork
localhost

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í.

V následujícím kvízu, Kvíz - Úvod, třídy a zapouzdření v PHP OOP, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 802x (1.97 kB)
Aplikace je včetně zdrojových kódů v jazyce PHP

 

Předchozí článek
Řešené úlohy k 1.-3. lekci OOP v PHP
Všechny články v sekci
Objektově orientované programování (OOP) v PHP
Přeskočit článek
(nedoporučujeme)
Kvíz - Úvod, třídy a zapouzdření v PHP OOP
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
227 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity