Jeden z hlavních principů OOP je tzv. **princip zapouzdření**, který říká, že by se měly složité úlohy rozdělit na mnoho malých problémů, které umíme řešit samostatně a najednou. Zároveň nás jako uživatele nezajímá, jak se to stane a data (vnitřní stav) zůstanou izolována.
Pokud například řešíme úlohu, jak na základě uživatelského dotazu s výrazem (5+3)*(2/(7+3))
vrátit výsledek 1.6
, tak pravděpodobně nikdo z nás nedokáže napsat jednu funkci nebo metodu, která tuto úlohu vyřeší najednou.
TIP: Hotové řešení tohoto typu příkladu je ve článku Zpracování matematického výrazu jako řetězec, ale připravte se ale na to, že to není nic lehkého.
Díky zapouzdření budete moci objekty používat "jako uživatel", tedy volat jejich metody a vůbec neřešit, jak vnitřně fungují.
Dejme tomu, že řešíme výpočet mzdy zaměstnance a chceme k tomu použít již hotovou třídu od jiného programátora. Stačí nám pouze znát povinné parametry konstruktoru a můžeme třídu "prostě používat":
$mzda = new MzdaZamestnance(25000, // hrubá mzda6, // počet let ve firmě10, // počet let praxetrue // je to muž?);echo $mzda->getHruba(); // 25000echo $mzda->getCista(); // 17800
Parametry objektu jsou smyšlené a neodpovídají reálně tomu, jak se mzda počítá. Princip ilustruje zejména to, že nám stačí znát pouze obecné veřejné rozhraní a nemusíme vůbec řešit vnitřní stav objektu, dokonce ani vnitřní implementaci a už vůbec proč to funguje tak, jak to funguje. Jednoduše zavoláme metodu getCista()
a dostaneme čistou mzdu.
Je důležité si uvědomit, že samotné zapouzdření není vlastnost ani syntaxe jazyka. To, že je třída a aplikace zapouzdřená je pouze otázka návrhu aplikace od programátora a to, že o kódu přemýšlí.
Vždy přemýšlejte při návrhu třídy takto:
Pro property a metody, které řeší vnitřní logiku, dává smysl nastavit viditelnost jako private
. Hlavní výhoda je zejména v tom, že nepůjdou volat zvenku a uživatel bude nucen použít vaše navržené rozhraní, díky čemuž si ochráníte data a vnitřní stav objektu.
Například mějme objekt reprezentující bankovní účet, na který chceme vkládat platby a řešit aktuální zůstatek:
class BankAccount{private int $sum;public function __construct(int $startSum){$this->sum = $startSum >= 0 ? $startSum : 0;}public function getSum(): int{return $this->sum;}public function pay(int $price): void{$newSum = $this->sum - $price;if ($newSum < 0) {throw new \Exception('Tolik peněz nemáte!');}$this->sum = $newSum;}public function addMoney(int $money): void{$this->sum += $money;}}
Všimněte si toho, že třída obsahuje pouze jedinou private
property $sum
, která obsahuje aktuální zůstatek.
Pokud chceme zjistit aktuální zůstatek, existuje pro to metoda getSum()
, nicméně novou hodnotu zůstatku nemáme vůbec jak změnit. Můžeme pouze peníze odebírat metodou pay()
nebo přidávat metodou addMoney()
.
Díky tomuto principu vždycky bezpečně víme, že nám nikdo nemůže objekt rozbít.
Pokud se uživatel pokusí zaplatit více peněz, než kolik je reálně na účtu, metoda pay()
to nedovolí, protože ještě před přepsáním property $sum
provede kontrolní výpočet a pokud by měl být zůstatek záporný (menší než nula), vyhodí se chybová výjimka a operace se zastaví.
Ukázali jsme si základní princip zapouzdření, který nám umožňuje lépe přemýšlet nad abstrakcí objektů a přináší úplně nový pohled na věc.
Až tento princip dobře pochopíte, uvidíte, že vám začnou dávat frameworky obrovský smysl, protože interně zapouzdřují mnoho chytrosti, kterou můžete jen používat.
Příště se podíváme na Dědičnost a viditelnost.
Jan Barášek Více o autorovi
Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.
Rád vám pomůžu:
Nabízím trénink vývojářů, konzultace, školení a analýzu návrhových vzorů. Osobně v Praze nebo online.
Napište mi, pokud si nevíte rady.
Lektor: Jan Barášek
Články píše Jan Barášek © 2009-2024 | Kontakt | Mapa webu
Status | Aktualizováno: ... | cs