11 Diagram tříd, asociace, dědičnost, abstraktní třídy

Rozměr: px
Začít zobrazení ze stránky:

Download "11 Diagram tříd, asociace, dědičnost, abstraktní třídy"

Transkript

1 11 Diagram tříd, asociace, dědičnost, abstraktní třídy Studijní cíl Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost diagramům tříd, asociaci, dědičnosti a abstraktním třídám. Doba nutná k nastudování 2 2,5 hodiny 11.1 Diagram tříd V minulém bloku jsme se seznámili s ikonou třídy, která se omezuje svým pohledem pouze na jednu třídu. Nyní se podívám na rozsáhlejší přehled o třídách, který nám umožňuje diagram tříd viz Obrázek 1. Diagram tříd umožňuje graficky dokumentovat vztah mezi třídami. Jak jsme si již uvedli v kapitole věnující se třídám, tak se program v jazyce Java skládá z celé řady tříd, které mají být nezávislé. Obrázek 1: Ukázka diagramu tříd KST/IZAPR - Základy programování blok 11, strana 1 (8) Michael Bažant

2 11.2 Asociace Existuje více asociačních vazeb mezi třídami, my se nyní omezíme se pouze na jednoduchou asociaci. Tento typ vazby používáme v případech, kdy můžeme vyjádřit vazbu mezi třídami slovesem má viz Obrázek 1, kde jeden ovladač má jeden DVD přehrávač. Orientace hrany mezi těmito třídami představuje tok informací, v tomto případě tedy ovladač posílá informace dvd přehrávači (např. pokyny přehraj, zastav přehrávání apod.). Dalším typům asociačních vazeb (např. agregace, kompozice apod.) bude věnována pozornost v předmětu Objektově orientované programování. V jazyce Java asociační vazbu mezi třídami zapisujeme pomocí referenční proměnné, která je deklarována ve třídě, ze které vychází orientovaná hrana asociace. Příklad: public class Ovladac { public DVDPrehravac dvdprehravac; } public Ovladac() { } U asociační hrany jsou k dispozici informace jak o názvu referenční proměnné, tak o jejím přístupovém právu a také o násobnosti. V našem případě se jedná o násobnost 1:1, což znamená, že jeden ovladač ovládá jeden dvd přehrávač. Obecně lze říci, že je možné používat libovolné násobnosti, které se zapisují k asociační hraně, např. 1:2, 1:m, m:n apod Dědičnost Dědičnost používáme v případech, kdy dvě nebo více tříd mají společné prvky a dědičnost může pomoci v odstranění duplicit ve zdrojovém kódu. Hned na úvod výkladu dědičnosti je ale nutné upozornit na to, že je velkou chybou používat dědičnost pouze na základě úsudku o tom, že nějaké třídy mají společné prvky a tak lze použít dědičnost pro odstranění duplicit. Můžeme se podívat na jednoduchý příklad, ve kterém figurují geometrické tvary, které chceme vykreslit na nějaký formulář. KST/IZAPR - Základy programování blok 11, strana 2 (8) Michael Bažant

3 Obrázek 2: Geometrické tvary Na první pohled je zřejmé, že tyto tvary disponují prvky, které jsou pro všechny tyto tvary společné. Mohli bychom tedy založit třídu Tvar, která by obsahovala společné prvky pro tyto třídy. Pro rozhodnutí o tom, zda použít mezi třídami vazbu tyto dědičnost je rozhodující, zda získáme kladnou odpověď na otázku je obdélník tvarem? Pokud je odpověď kladná, je možné použít mezi třídami dědičnost viz Obrázek 3, kdy třída, která má společné atributy se nazývá předek a třídy, které dědí, se nazývají potomci. V diagramu tříd je tato vazba znázorněna orientovanými hranami, jejichž orientace vede k předkovi. Orientované hrany u asociace a dědičnosti se liší svým tvarem viz Obrázek 1 a Obrázek 3. Obrázek 3: Dědičnost mezi třídami V jazyce Java zapisujeme dědičnost pomocí klíčového slova extends ve třídě potomka (daná třída tedy rozšiřuje třídu předka) viz Obrázek 4. KST/IZAPR - Základy programování blok 11, strana 3 (8) Michael Bažant

4 Obrázek 4: Zápis dědičnosti v jazyce Java V jazyce Java (na rozdíl od jiných jazyků) není povolena vícenásobná dědičnost, tzn., že jedna třída může mít maximálně jednoho předka. Jeden předek samozřejmě může mít i více potomků viz Obrázek 3. V terminologii programování hovoříme také o tom, že předek je vždy třídou, která je více abstraktní než potomek a potomek je třídou, která je více konkrétní než předek. Každá třída má svého předka, i pokud žádného nedeklarujeme explicitně viz Obrázek 5. Obrázek 5: Implicitní dědičnost Každý potomek v sobě nese informace, kterými disponuje předek a dále k těmto informacím přidává své vlastní informace viz Obrázek 6. Obrázek 6: Příklad dědičnosti KST/IZAPR - Základy programování blok 11, strana 4 (8) Michael Bažant

5 Třída Object je základní třídou, která je předkem pro všechny třídy, které explicitně nedeklarují předka jiného. Třída java.lang.object disponuje několika veřejnými metodami, se kterými je dobré se seznámit, např. metoda tostring() vrací textovou reprezentaci objektu metoda equals(object obj) vrací, zda se jedná o objekt, který je ekvivalentní k jinému objektu metoda hashcode() vrací hash kód objektu metoda clone() vytváří a vrací kopii objektu Dědičnost a konstruktory Potomek vždy rozšiřuje svého předka, a proto je vždy nutné vytvořit objekt předka ještě před tím, než je vytvořen objekt potomka. Z tohoto důvodu je v konstruktoru potomka vždy nejdříve volán konstruktor předka (musí na prvním řádku konstruktoru potomka) a to buď implicitně (pokud jej nevoláme explicitně) nebo máme možnost jej volat explicitně. Implicitně je vždy volán bezparametrický konstruktor předka, a pokud tento není k dispozici, je nutné volat parametrický konstruktor předka explicitně pomocí klíčového slova super. Obrázek 7: Implicitní volání konstruktoru předka 11.4 Dědičnost přístupová práva U dědičnosti je možné využívat modifikátor protected. Následující tabulka rekapituluje přístupová práva, která jsme si již představili v předchozím bloku a také přehledně znázorňuje přístupová práva od nejvíce restriktivního private až po nejméně striktní public. KST/IZAPR - Základy programování blok 11, strana 5 (8) Michael Bažant

6 Obrázek 8: Přístupová práva Příklad na přístupová práva v hierarchii dědičnosti a v různých balíčcích (p1, p2) demonstruje následující příklad: Obrázek 9: Příklad na využití přístupových práv 11.5 Dědičnost překrývání metod Potom dědí jak atributy, tak metody od svého předka. V potomkovi je možné změnit implementaci metody předka pomocí tzv. překrývání metod (method overriding). Typicky se tato technika využívá např. u metody tostring() apod. Metody mohou být překryty pouze tehdy, pokud jsou dostupné, privátní metody nejsou dostupné mimo třídu, kde jsou definovány, a proto nemohou být překryty. V takovém případě se nejedná o překryté metody, ale zcela nezávislé metody. Pakliže se má jednat o překrývání metod, jak je nezbytné, aby byla shoda v názvu metody, v návratovém typu, v seznamu parametrů a přístupová práva nemohou být více restriktivní. KST/IZAPR - Základy programování blok 11, strana 6 (8) Michael Bažant

7 Pro dokumentaci rozdílu mezi přetěžováním a překrýváním metod slouží následující obrázek viz Obrázek 10: Rozdíl mezi překrýváním a přetěžováním metod 11.6 Abstraktní třídy V jazyce Java je možné v deklaraci tříd zapsat, že není možné na základě dané třídy vytvářet objekty. Takovým třídám říkáme abstraktní třídy a používáme u nich modifikátor abstract. V ikoně třídy tuto skutečnost znázorňujeme pomocí využití písma kurzíva viz Obrázek 11, kde figuruje abstraktní třída Zamestnanec. Obrázek 11: Abstraktní třída zaměstnanec KST/IZAPR - Základy programování blok 11, strana 7 (8) Michael Bažant

8 Otázky na procvičení 1. Jaký je rozdíl mezi přetěžováním a překrýváním metod? 2. Co je to překrývání metod? 3. Co platí z hlediska dědičnosti pro přístupová práva protected? 4. Může mít v jazyce Java potomek více předků? 5. Co je to asociační vazba? Odkazy a další studijní prameny 1. Java Tutorial - KST/IZAPR - Základy programování blok 11, strana 8 (8) Michael Bažant