Vae jistota na trhu IT Ddn implementace Rudolf

  • Slides: 73
Download presentation
Vaše jistota na trhu IT Dědění implementace Rudolf Pecinovský rudolf@pecinovsky. cz

Vaše jistota na trhu IT Dědění implementace Rudolf Pecinovský rudolf@pecinovsky. cz

Vaše jistota na trhu IT Obsah s odkazy ►Rozhraní a abstraktní třídy ►Principy dědění

Vaše jistota na trhu IT Obsah s odkazy ►Rozhraní a abstraktní třídy ►Principy dědění tříd ►přebíjení metod ►Podrobnosti o konstruktorech ►Společný rodič skupiny tříd ►Kdy dědění ano a kdy ne

Vaše jistota na trhu IT Opakování: Rozhraní a dědění ►Rozhraní a jeho implementace (opakování)

Vaše jistota na trhu IT Opakování: Rozhraní a dědění ►Rozhraní a jeho implementace (opakování) ►Implementace více rozhraní ►Dědění rozhraní ►Přetypování na rodiče a potomka ►Ukázka programu s přetypováním

Rozhraní a jeho implementace (opakování) ► V definici datového typu rozlišujeme rozhraní a implementaci

Rozhraní a jeho implementace (opakování) ► V definici datového typu rozlišujeme rozhraní a implementaci ► V rozhraní rozlišujeme dvě složky: ● Signaturu definující část rozhraní, kterou může překladač ověřit ● Kontrakt, definující požadavky, které musí programátor doplnit, ale které není možno postihnout v syntaxi ► Konstrukce interface slouží jako specifikace požadované signatury třídy umožňující popsat i kontrakt ► Všechny metody deklarované v rozhraní jsou abstraktní, tj. bez jakékoliv implementace í n vá ► Třída implementující interfejs musí implementovat všechny jím deklarované metody nebo se prohlásit za abstraktní o k a ► Instance třídy implementující rozhraní se mohou vydávat za instance daného rozhraní p O ► Třída může implementovat libovolný počet rozhraní Copyright © 2006, Rudolf Pecinovský VŠE – 05 4

Implementace více rozhraní ► Implementované interfejsy uvádí třída ve své hlavičce za klíčovým slovem

Implementace více rozhraní ► Implementované interfejsy uvádí třída ve své hlavičce za klíčovým slovem implements; při současné implementaci více interfejsů oddělujeme jednotlivá rozhraní čárkou, např. public clas Třída implements Rozhraní 1, Rozhraní 1 ► UML zobrazuje implementaci rozhraní čárkovanou šipkou s trojúhelníkovou hlavičkou ► Implementovaná rozhraní počítáme mezi předky implementující třídy ► Implementující třídy vystupují naopak jako potomci svých implementovaných rozhraní í n vá o k a p O ► Instance potomka se může kdykoliv vydávat za instanci předka Copyright © 2006, Rudolf Pecinovský VŠE – 05 5

Dědění rozhraní ► Rozhraní může být potomkem jiného rozhraní; svého rodiče pak uvede v

Dědění rozhraní ► Rozhraní může být potomkem jiného rozhraní; svého rodiče pak uvede v hlavičce za slovem extends ► Třídy implementující dceřiné rozhraní musí implementovat všechny jeho metody včetně zděděných Copyright © 2006, Rudolf Pecinovský ak Op ► Dceřiné rozhraní přebírá (dědí) všechny metody deklarované rodičem ov ► V diagramu tříd znázorňujeme vztah předek–potomek šipkou s trojúhelníkovým koncem ukazujícím k předku án í interface IHýbací extends IPosuvný, INafukovací VŠE – 05 6

Přetypování instancí rozhraní ► Prostřednictvím implementace rozhraní s více předky můžeme vyřešit problém parametrů

Přetypování instancí rozhraní ► Prostřednictvím implementace rozhraní s více předky můžeme vyřešit problém parametrů metod vystupujících jako instance několika typů současně ► Víme-li, že instance nějakého typu je současně instancí jiného typu, můžeme ji přetypovat ► Přetypování potomka na předka provede překladač automaticky ● Instance třídy implementující rozhraní se může kdykoliv vydávat za instanci kteréhokoliv z implementovaných rozhraní ● Instance potomka rozhraní se může kdykoliv vydávat za instanci předka tohoto rozhraní ► Přetypování se uplatní, potřebujeme-li s instancí vydávající se za instanci některého ze svých předků pracovat opět jako s instancí jejího vlastního typu í n vá o k a p O Copyright © 2006, Rudolf Pecinovský VŠE – 05 7

Ukázka programu s přetypováním na potomka public class Pozice { public final int x,

Ukázka programu s přetypováním na potomka public class Pozice { public final int x, y; //. . . Vynechané metody } @Override public boolean equals( Object o ) { if( !(o instanceof Pozice) ) return false; Pozice p = (Pozice) o; return (x == p. x) && (y == p. y); } í n vá o k a p O Copyright © 2006, Rudolf Pecinovský VŠE – 05 8

Vaše jistota na trhu IT Principy dědění ►Specializace × Zobecnění ►Terminologie a základní vztahy

Vaše jistota na trhu IT Principy dědění ►Specializace × Zobecnění ►Terminologie a základní vztahy ► 3 druhy dědění

Specializace ► Typ: třída (class) / rozhraní (interface) / výčtový typ (enum) ► Při

Specializace ► Typ: třída (class) / rozhraní (interface) / výčtový typ (enum) ► Při práci s objekty daného typu často odhalíme skupiny instancí se speciálními, avšak pro celou skupinu společnými vlastnostmi ► Příklady: ● Auta můžeme dělit na osobní, nákladní, autobusy a speciální ● Vesmírná tělesa dělíme na hvězdy, planety a ostatní smetí ● Osoby dělíme na muže a ženy ● Zpomezi geometrických tvarů můžeme vydělit skupiny elips, n-úhelníků, … ● Mezi čtyřúhelníky můžeme vydělit obdélníky, mezi nimi pak čtverce ► To, že je daný objekt členem speciální podskupiny nijak neovlivňuje jeho členství v původní skupině ● Proto se může potomek kdykoliv vydávat za předka Copyright © 2006, Rudolf Pecinovský VŠE – 05 10

Zobecnění ► Často provádíme obrácený myšlenkový postup: u řady různých druhů objektů nacházíme společné

Zobecnění ► Často provádíme obrácený myšlenkový postup: u řady různých druhů objektů nacházíme společné vlastnosti a definujeme pak společné skupiny ► Příklady: ● Lidé spolu s řadou zvířecích druhů tvoří skupiny savců ● Auta, kola, povozy, vlaky, letadla, lodě & spol. jsou dopravní prostředky ● Kybernetika je věda o řízení a sdělování v živých organizmech, společenstvích a strojích => jako kybernetický systém lze považovat každý člen každé ze skupin ● Přirozené číslo je speciálním případem celého čísla, které je speciálním případem racionálního čísla, které je speciálním případem reálného čísla, které je speciálním případem komplexního čísla ● V objektově orientovaných programech je vše považováno za objekt Copyright © 2006, Rudolf Pecinovský VŠE – 05 11

Terminologie a základní vztahy ► Typ: třída (class) / rozhraní (interface) / výčtový typ

Terminologie a základní vztahy ► Typ: třída (class) / rozhraní (interface) / výčtový typ (enum) ► Pro podmnožinu instancí se speciálními vlastnostmi můžeme definovat jejich vlastní typ ► Pro označení „obecnějšího“ a „specializovaného“ typu se používají různé termíny: Zobecněný Rodičovský typ Bázový typ Nadtyp, nadtřída Předek Specializovaný Dceřiný typ Odvozený typ Podtyp, podtřída Potomek ► Za předky třídy považujeme i všechna implementovaná rozhraní Copyright © 2006, Rudolf Pecinovský VŠE – 05 12

3 druhy dědění ► Potomci mohou od svých rodičů leccos převzít; toto převzetí označujeme

3 druhy dědění ► Potomci mohou od svých rodičů leccos převzít; toto převzetí označujeme termínem dědění ► V OOP existují 3 druhy dědění: ● Dědění rozhraní ● Dědění implementace ● Dědění podstaty (potomek je speciálním případem předka) ► Má-li program spolehlivě fungovat, musejí být všechny tři druhy dědění v souladu ● Vyžaduje-li konkrétně řešený problém tento soulad narušit, je třeba tuto skutečnost důkladně zdokumentovat Copyright © 2006, Rudolf Pecinovský VŠE – 05 13

Dědění rozhraní ► O dědění rozhraní předka hovoříme nezávisle na tom, je-li předkem třída

Dědění rozhraní ► O dědění rozhraní předka hovoříme nezávisle na tom, je-li předkem třída nebo interface ► Dědění rozhraní vyžaduje, aby potomek dodržel veškerou signaturu a kontrakt rozhraní předka (Liskov Substitution Principle – LSP) ► Korektně implementované zděděné rozhraní umožňuje, aby se instance potomka mohla vydávat za instanci předka ► Narušení dědění rozhraní (většinou tak, že potomek nedodrží kontrakt předka) snižuje stabilitu programu ► Příklady řádného dědění: ● HTML spojení je potomek obecného spojení ● Třída Array. List je potomkem rozhraní List ● Třída File. Input. Stream je potomkem třídy Input. Stream ● Čtverec lze v jistých situacích považovat za speciální případe obdélníka Copyright © 2006, Rudolf Pecinovský VŠE – 05 14

Dědění implementace ► Dědění implementace je speciální případ skládání, při němž potomek převezme instanci

Dědění implementace ► Dědění implementace je speciální případ skládání, při němž potomek převezme instanci předka jako svůj podobjekt a současně převezme i jeho rozhraní ► Používá se především proto, aby potomek získal „zdarma“ implementaci některých potřebných atributů, metod a typů ► Překladač zabezpečí automatické převzetí signatury, dodržení příslušného kontraktu má na starosti programátor ► Autoři potomků dědících implementaci se často soustředí pouze na to, aby získali implementaci „zdarma“, a zcela ignorují nutnost dodržení kontraktu a invariantů předka ► Důsledek: instance potomka se nemůže plnohodnotně vydávat za instanci předka; porušuje tak LSP a konzistenci programu Copyright © 2006, Rudolf Pecinovský VŠE – 05 15

Nevhodné použití dědění implementace ► Obdélník je potomek čtverce ● Obdélník je implementován jako

Nevhodné použití dědění implementace ► Obdélník je potomek čtverce ● Obdélník je implementován jako čtverec, který nemusí mít všechny strany stejně dlouhé ► Obdélník je potomek bodu ● Obdélník zdědí souřadnice jednoho rohu a přidá souřadnice dalšího ► Kruh je potomek bodu ● Kruh je implementován jako bod doplněný o poloměr ► Kruhová výseč je potomek kruhu ● Výseč je implementována jako kruh doplněný o úhel výseče ► Cyklista je potomek žáby ● Cyklista neumí přeskákat potok po kamenech. Po jeho předefinování jako potomka žáby tuto schopnost získá. Současně ale zdědí schopnost kvákat a rodit pulce. Výsledný objekt proto není cyklista, který umí skákat po kamenech, ale žába, která umí jezdit na kole. Copyright © 2006, Rudolf Pecinovský VŠE – 05 16

Dědění podstaty ► O dědění podstaty hovoříme tehdy, můžeme-li považovat instance potomka za speciální

Dědění podstaty ► O dědění podstaty hovoříme tehdy, můžeme-li považovat instance potomka za speciální případy instancí předka ► O dědění podstaty lze uvažovat nezávisle na implementaci ► Příklady: ● Mapa je speciální typ množiny – je to množina dvojic (klíč, hodnota). Ve skutečnosti (standardní knihovna Javy) je však množina implementována jako mapa ● Kruh chápeme jako speciální případ elipsy a obdobně chápeme čtverec jako speciální případ obdélníku. Tuto dědění však nemůžeme použít v aplikacích, v nichž potřebujeme realizovat operace, které svobodně mění oba rozměry daného grafického objektu ► Při návrhu architektury stavějící na dědění podstaty můžeme občas narazit na problémy se správnou implementací takto pojatého dědění Copyright © 2006, Rudolf Pecinovský VŠE – 05 17

Vaše jistota na trhu IT Návrhový vzor Dekorátor

Vaše jistota na trhu IT Návrhový vzor Dekorátor

Předběžné úvahy ► Máme auta, která se umějí přesunout na zadanou pozici, ale nejsou

Předběžné úvahy ► Máme auta, která se umějí přesunout na zadanou pozici, ale nejsou připravena na přímé ovládání z klávesnice ► Ovládání z klávesnice může zprostředkovat instance třídy Řadič, která zprostředkuje ovládání instancím typu IOvládaný ► Znalci dědění navrhnou definovat ovládaná auta jako potomky dodaných, ale tak v projektu vznikne řada nových tříd ► Výhodnější je použít vzor Dekorátor a schopnost „být ovládán“, tj. implementaci rozhraní IOvládaný přidat jako „dekoraci“ Copyright © 2006, Rudolf Pecinovský VŠE – 05 19

Návrhový vzor Dekorátor ► Název Dekorátor obdržel vzor proto, že dekoruje (ozdobí) dodaný (dekorovaný)

Návrhový vzor Dekorátor ► Název Dekorátor obdržel vzor proto, že dekoruje (ozdobí) dodaný (dekorovaný) objekt novou (nebo upravenou) funkčností ► Dekorátor přebírá rozhraní předka včetně kontraktu, takže může kdykoliv vystupovat v roli dekorovaného „předka“ ► Mohli bychom jej označit jako explicitně definovanou dědění: dekorující objekt (dekorátor) vystupuje v roli potomka, dekorovaný objekt v roli předka ► Dekorátor explicitně implementuje všechny „nedotčené“ metody „předka“ s tím, že zodpovědnost za jejich korektní provedení přenechává na podobjektu „předka“ ► Je obzvláště výhodný v situacích, kdy mechanické použití dědění vede k dramatickému nárůstu počtu tříd a citelnému snížení modifikovatelnosti programu Copyright © 2006, Rudolf Pecinovský VŠE – 05 20

Definice dekorátoru public class Ovládaný implements IPosuvný, IOvládaný { private final IPosuvný posuvný; Konstruktor

Definice dekorátoru public class Ovládaný implements IPosuvný, IOvládaný { private final IPosuvný posuvný; Konstruktor dekorátoru public Ovládaný (IPosuvný posuvný) { this. posuvný = posuvný; } public Pozice get. Pozice() { return posuvný. get. Pozice(); } public void set. Pozice(Pozice p) { posuvný. set. Pozice(p); } } //. . . a další Copyright © 2006, Rudolf Pecinovský VŠE – 05 převezme dekorovaný objekt jako parametr Zprávy, jejichž realizaci dekorátor deleguje na dekorovaný objekt Dekorující objekt rozhodne, pro které činnosti využije metod dekorovaného objektu a pro které definuje metody vlastní 21

x Adaptér pro skupinu dekorátorů ► Dekorátor „přehrává“ volání „nezdobících“ metod na metody ozdobeného

x Adaptér pro skupinu dekorátorů ► Dekorátor „přehrává“ volání „nezdobících“ metod na metody ozdobeného objektu ► Očekáváme-li vytváření více dekorujících objektů, má smysl pro ně definovat společného rodiče, který se postará o toto „přehrávání“ Copyright © 2006, Rudolf Pecinovský VŠE – 05 22

x Definice společného rodiče public class Ad. Otočný implements IOtočný { private final IOtočný

x Definice společného rodiče public class Ad. Otočný implements IOtočný { private final IOtočný otočný; public Ad. Otočný(IOtočný otočný) { this. otočný = otočný; } public Pozice get. Pozice() { return otočný. get. Pozice(); } public void set. Pozice(Pozice p) { otočný. set. Pozice(p); } } //. . . a další Copyright © 2006, Rudolf Pecinovský VŠE – 05 23

Vaše jistota na trhu IT Implementace dědění tříd ►Co se dědí ►Rodičovský podobjekt ►Konstrukce

Vaše jistota na trhu IT Implementace dědění tříd ►Co se dědí ►Rodičovský podobjekt ►Konstrukce objektu

? Co se vlastně dědí Všech Copyright © 2006, Rudolf Pecinovský VŠE – 05

? Co se vlastně dědí Všech Copyright © 2006, Rudolf Pecinovský VŠE – 05 25

Co se vlastně dědí – rodičovský podobjekt ► Aby bylo možno zabezpečit funkci všech

Co se vlastně dědí – rodičovský podobjekt ► Aby bylo možno zabezpečit funkci všech (i soukromých) vazeb, obsahuje každý objekt dceřiné třídy jako svoji součást podobjekt své rodičovské třídy, který s sebou přináší požadovanou implementaci Object Matka Dcera Vnučka ► Dceřiná třída tak dědí od svého rodiče všechny jeho schopnosti; přebírá všechny jeho členy včetně soukromých, o kterých vůbec „neví“ ► Objekt dceřiné třídy se nemůže začít budovat dřív, než bude zcela vybudován jeho rodičovský podobjekt ● U rodičovského podobjektu aplikujeme stejné pravidlo – před ním je tedy třeba vybudovat prarodičovský podobjekt, před ním praprarodičovský atd. Copyright © 2006, Rudolf Pecinovský VŠE – 05 26

Atribut super ► Rodičovský podobjekt je vytvořen jako „soukromý atribut“ nazvaný super, tímto identifikátorem

Atribut super ► Rodičovský podobjekt je vytvořen jako „soukromý atribut“ nazvaný super, tímto identifikátorem jej lze „oslovovat“ ► Tento atribut ale není plnohodnotný: ● Smí jej používat pouze jeho vlastník, tj. nelze zavolat param. super. to. String() ● Nelze jej používat samotný, musím po něm vždy chtít nějaký člen (atribut, metodu, datový typ) ● Potřebujeme-li jej zkonstruovat pomocí parametrického konstruktoru, zavoláme na počátku těla konstruktoru super(/*parametry*/); ● Aby mohla mít třída potomky, nesmí mít konstruktor soukromý Copyright © 2006, Rudolf Pecinovský VŠE – 05 27

Konstrukce objektu 1. Zkontroluje se, že je zavedena třída 1. Při zavádění musí být

Konstrukce objektu 1. Zkontroluje se, že je zavedena třída 1. Při zavádění musí být zaveden rodič => nejprve se zavede rodičovská třída 2. Pak se zavede dceřiná třída 2. Zavolá se operátor new 1. Připraví prostor na haldě a připojí odkaz na VMT 2. Mezi parametry přidá odkaz this a vyhodnotí zbylé parametry Předává-li konstruktor zodpovědnost za inicializaci svému kolegovi, pokračuje se ve vyhodnocování parametrů, dokud se nenarazí na konstruktor, který inicializaci doopravdy provede 3. Zavolá se konstruktor 1. Zavolá se konstruktor rodičovského podobjektu (super) 2. Projde se definice třídy, inicializují se atributy a provedou inicializační bloky 3. Vstoupí se do těla konstruktoru a to se provede 4. Odkaz na vytvořenou instanci se předá volající metodě Demo: Copyright © 2006, Rudolf Pecinovský Matka – Dcera – Vnučka VŠE – 05 28

Hierarchie dědění ► Dědění tříd má v jazyku Java stromovou strukturu, v jejímž kořeni

Hierarchie dědění ► Dědění tříd má v jazyku Java stromovou strukturu, v jejímž kořeni je třída Object ● Každá třída s výjimkou třídy Object má právě jednoho předka ● Třída Object je společným (pra)rodičem všech tříd ► Každá uživatelem definovaná třída má právě jednoho předka, tj. smí obsahovat pouze jeden rodičovský podobjekt ► Na rozdíl od některých jiných jazyků (např. C++) jazyk Java nepodporuje násobnou dědění tříd ● Přináší problémy při implementaci a programy jsou méně stabilní ● Přináší problémy při návrhu, protože nabízí návrhářům řešení, z kterého se po odhalení jeho nevýhodnosti špatně couvá ● Přináší problémy při modifikacích programu, protože zbytečně zvyšuje počet vzájemných vazeb, které je při modifikaci nutno respektovat Copyright © 2006, Rudolf Pecinovský VŠE – 05 29

Deklarace dědění ► Svoje odvození od rodičovské třídy deklaruje dceřiná třída v hlavičce za

Deklarace dědění ► Svoje odvození od rodičovské třídy deklaruje dceřiná třída v hlavičce za svým názvem klíčovým slovem extends následovaným úplným názvem rodičovské třídy ► Je-li rodičovská třída ve stejném balíčku nebo je-li importovaná, lze úplný název nahradit jednoduchým ► Třídy z kořenového balíčku nemají úplný název, a proto nemohou mít potomky v jiných balíčcích ► Dědictví od třídy Object se uvádět nemusí a naopak, nemá-li někdo v hlavičce uvedeného předka, je přímým potomkem třídy Object ► Případná deklarace implementace rozhraní se uvádí až za deklarací dědění: public class Potomek extends Předek implements Rozhraní Copyright © 2006, Rudolf Pecinovský VŠE – 05 30

Příklady dědění z knihovny kolekcí Object public abstract class Abstract. Collection implements Collection public

Příklady dědění z knihovny kolekcí Object public abstract class Abstract. Collection implements Collection public abstract class Absttract. List extends Abstract. Collection implements List public class Array. List extends Abstract. List implements Random. Access public class Linked. Hash. Set extends Hash. Set Copyright © 2006, Rudolf Pecinovský VŠE – 05 31

Modifikátor protected ► Definuje přístup, který je rozšířením implicitního přístupu ► Členy (atributy, metody,

Modifikátor protected ► Definuje přístup, který je rozšířením implicitního přístupu ► Členy (atributy, metody, zanořené typy) označené modifikátorem protected jsou viditelné: ● Pro všechny třídy uvnitř stejného balíčku ● Pro dceřiné třídy v jakémkoliv balíčku ► Členy s modifikátorem protected jsou v překladech označovány jako chráněné ► Má-li třída či instance atribut, který je instancí této třídy nebo její rodičovské třídy, jsou pro ni jeho chráněné členy nepřístupné Copyright © 2006, Rudolf Pecinovský VŠE – 05 public class Seznam { protected Uzel první; protected Uzel poslední; } public class protected } Uzel { Uzel předchůdce; Uzel následník; Object hodnota; 32

Vaše jistota na trhu IT Abstraktní třídy a návrhový vzor Šablonová metoda ►Abstraktní třídy

Vaše jistota na trhu IT Abstraktní třídy a návrhový vzor Šablonová metoda ►Abstraktní třídy ►Abstraktní metody ►Potomci abstraktní třídy ►Ještě jednou architektura knihovny kolekcí

Motivace ► Občas se hodí, aby část rozhraní byla již implementována a potomci mohli

Motivace ► Občas se hodí, aby část rozhraní byla již implementována a potomci mohli tuto implementaci zdědit ► Příklad: Většina tříd implementujících interface IPosuvný bude mít definovány metodu set. Pozice(Pozice) stejně: public class Posuvný implements IPosuvný { public Pozice get. Pozice() { //Definice těla metody } public void set. Pozice(int x, int y) { //Definice těla metody } public void set. Pozice(Pozice pozice) { set. Pozice(pozice. x, pozice. y); } //Další atributy a metody } Copyright © 2006, Rudolf Pecinovský VŠE – 05 Metody, které definuje každá třída po svém Metoda, kterou většina tříd definuje stejně 34

Abstraktní třídy ► Abstraktní třída je hybrid na pomezí mezi standardní třídou a rozhraním

Abstraktní třídy ► Abstraktní třída je hybrid na pomezí mezi standardní třídou a rozhraním ● Na rozdíl od rozhraní může některé metody implementovat ● Na rozdíl od standardní třídy nemusí implementovat všechny metody ► Abstraktní třída se musí ke své abstraktnosti přihlásit uvedením klíčového slova abstract mezi svými modifikátory ● Příklad: public abstract class Moje. Třída {} ► Protože abstraktní třídy nemusí mít vše implementované, nemůže mít žádné samostatné instance; instance může vytvářet jen třída s kompletní implementací ► S instancemi je na tom abstraktní třída obdobně jako rozhraní: za instance abstraktní třídy se vydávají instance jejích potomků ► Třídu (metodu), která není abstraktní, označujeme jako konkrétní Copyright © 2006, Rudolf Pecinovský VŠE – 05 35

Abstraktní metody ► Abstraktní třída může deklarovat vlastní abstraktní metody, musí však mezi jejich

Abstraktní metody ► Abstraktní třída může deklarovat vlastní abstraktní metody, musí však mezi jejich modifikátory uvést klíčové slovo abstract např. : abstract public void nakresli(Kreslítko k); ► Abstraktní metody nesmějí být soukromé, potomek by na ně neviděl a nemohl by je implementovat ► Deklaraci neimplementovaných metod deklarovaných v implementovaných rozhraních, není třeba opakovat (ale lze) ► Metody, které nejsou abstraktní, označujeme jako konkrétní ► Konkrétní metody mohou ve svých definicích používat všechny deklarované metody včetně abstraktních, přestože tyto nejsou v době jejich definice ještě implementovány Copyright © 2006, Rudolf Pecinovský VŠE – 05 36

Možné řešení ► Dovolíme třídě deklarovat abstraktní metody obdobně, jako to dělá interface, a

Možné řešení ► Dovolíme třídě deklarovat abstraktní metody obdobně, jako to dělá interface, a nechat implementaci na potomcích ► Musíme se však smířit s tím, že (stejně jako interface) tato třída nebude moci mít vlastní instance – označíme ji proto jako abstraktní public abstract class Posuvný implements IPosuvný { public abstract Pozice get. Pozice(); Abstraktní metody public abstract void set. Pozice(int x, int y); public void set. Pozice(Pozice pozice) { set. Pozice(pozice. x, pozice. y); } } //Další atributy a metody Copyright © 2006, Rudolf Pecinovský VŠE – 05 Metoda používající abstraktní metody, i když ještě nejsou implementovány 37

Potomci abstraktní třídy ► Třída se prohlásí za potomka jiné třídy tím, že za

Potomci abstraktní třídy ► Třída se prohlásí za potomka jiné třídy tím, že za název třídy napíše klíčové slovo extends následované názvem předka ► Třída smí mít pouze jediného „třídního“ předka; nezávisle na tomto „třídním“ předku však může implementovat libovolný počet rozhraní ► Potomek abstraktní třídy zdědí od svého rodiče všechny metody, avšak ty abstraktní musí buď implementovat, anebo se také prohlásit za abstraktní třídu ► Potomek abstraktní třídy automaticky dědí i implementaci všech rozhraní, k jejichž implementaci se rodičovská třída přihlásila ► Implementaci rozhraní dědí potomek nezávisle na tom, jestli požadované metody zdědí již implementované, anebo se bude muset postarat o jejich implementaci sám Copyright © 2006, Rudolf Pecinovský VŠE – 05 38

Knihovna kolekcí – architektura Copyright © 2006, Rudolf Pecinovský VŠE – 05 39

Knihovna kolekcí – architektura Copyright © 2006, Rudolf Pecinovský VŠE – 05 39

Návrhový vzor Šablonová metoda ► Motivace: Definujeme metodu obsahující kostru nějakého algoritmu, u nějž

Návrhový vzor Šablonová metoda ► Motivace: Definujeme metodu obsahující kostru nějakého algoritmu, u nějž však v době konstrukce ještě nejsou všechny kroky známy ► Konkrétní náplň neznámých kroků definují až potomci na základě svých speciálních dodatečných znalostí ► Třída se šablonovou metodou definuje příslušnou kostru a pro dosud neznámé postupy definuje virtuální metody, které potomci přebijí svými vlastními ● Je-li jedno zmožných řešení např. „nedělat nic“, je možno definovat virtuální metodu jako prázdnou ● Neexistuje-li žádné přijatelné implicitní řešení, definuje se metoda jako abstraktní Copyright © 2006, Rudolf Pecinovský VŠE – 05 40

Příklad: Třída Abstract. Collection 1/2 public abstract class Abstract. Collection<E> implements Collection<E> { /**

Příklad: Třída Abstract. Collection 1/2 public abstract class Abstract. Collection<E> implements Collection<E> { /** Vrací počet prvků v kolekci. */ public abstract int size(); /** Vrací informaci, zda je kolekce prázdná. */ public boolean is. Empty() { return size() == 0; } public abstract Iterator<E> iterator(); Copyright © 2006, Rudolf Pecinovský VŠE – 05 41

Příklad: Třída Abstract. Collection 2/2 public boolean contains(Object o) { Iterator<E> ie = iterator();

Příklad: Třída Abstract. Collection 2/2 public boolean contains(Object o) { Iterator<E> ie = iterator(); if (o==null) { while (ie. has. Next()) if (ie. next()==null) return true; } else { while (ie. has. Next()) if (o. equals(ie. next())) return true; } return false; } } Copyright © 2006, Rudolf Pecinovský VŠE – 05 42

Vaše jistota na trhu IT Přebíjení metod ►Virtuální a konečné metody ►Nebezpečné vlastnosti virtuálních

Vaše jistota na trhu IT Přebíjení metod ►Virtuální a konečné metody ►Nebezpečné vlastnosti virtuálních metod 103– 118 354– 429

Přebíjení metod ► Rodičovská třída může dovolit, aby dceřiná třída definovala vlastní verze metod,

Přebíjení metod ► Rodičovská třída může dovolit, aby dceřiná třída definovala vlastní verze metod, jejichž zděděné verze ji nevyhovují – tuto operaci označujeme jako přebití metody ► Rodič může zakázat přebíjení svých metod uvedením modifikátoru final ► Metody, které je možno přebít, označujeme jako virtuální ► přebít lze pouze metody, u nichž to není zakázané a na které třída vidí; neviditelné metody jsou nepřebitelné (private či „package private“ v jiných balíčcích) Copyright © 2006, Rudolf Pecinovský VŠE – 05 44

Dosažitelnost virtuálních metod ► Kdykoliv v budoucnu někdo pošle objektu zprávu, jejíž zpracování má

Dosažitelnost virtuálních metod ► Kdykoliv v budoucnu někdo pošle objektu zprávu, jejíž zpracování má na starosti virtuální metoda, bude vždy zavolána verze osloveného objektu, a to nezávisle na tom, za čí instanci se objekt v danou chvíli vydává ► Jakmile potomek přebije rodičovskou verzi metody, stane se přebitá verze pro okolí nedostupná ► O tom, která verze metody se použije, rozhoduje virtuální stroj až za běhu, a proto nezáleží na tom, které verze metod existovaly v době překladu volající metody Copyright © 2006, Rudolf Pecinovský VŠE – 05 45

Možná implementace přebíjení – VMT ► Součástí objektu třídy je tabulka virtuálních metod (virtual

Možná implementace přebíjení – VMT ► Součástí objektu třídy je tabulka virtuálních metod (virtual method table – VMT) ► Na počátku tabulky jsou zděděné metody, za nimi metody nové ► Je-li metoda přebitá, nahradí se její adresa adresou metody, která ji přebila ► Pošle-li někdo instanci třídy zprávu, zavolá se metoda na adrese ve VMT ► Ve VMT jsou pouze adresy virtuálních metod Copyright © 2006, Rudolf Pecinovský VŠE – 05 46

Použití přebité verze metody ► Přebití (overriding) není předefinování (redefining) ani přepsání (rewriting) přebité

Použití přebité verze metody ► Přebití (overriding) není předefinování (redefining) ani přepsání (rewriting) přebité metody ► Při přebití metody jinou metodou zůstává přebitá metoda nedotčená a můžete ji kdykoliv použít ► Dceřiná třída může použít přebitá verzi metody prostřednictvím kvalifikace klíčovým slovem super, pro ostatní třídy je však přebitá verze nedostupná Copyright © 2006, Rudolf Pecinovský VŠE – 05 47

Další vlastnosti přebíjení metod ► Přebíjející metoda musí mít stejnou signaturu (název, počet parametrů

Další vlastnosti přebíjení metod ► Přebíjející metoda musí mít stejnou signaturu (název, počet parametrů a jejich typy, typ návratové hodnoty) jako metoda přebíjená ► Od Javy 5 smí přebíjející metoda deklarovat návratový typ jako potomka návratové typu přebité metody ► Nemá-li metoda stejnou signaturu, nejedná se o přebití, ale o přetížení ► Napíšu-li před hlavičku anotaci @Override, bude překladač zkontrolovat, zda jsem metodu nepřetížil, ale opravdu přebil, ● Anotace @Override funguje plně až od verze 6. 0 ► Nechci-li umožnit potomkům metodu přebít, označím metodu modifikátorem final ● Při překladu volání konečných metod (stejně jako při překladu soukromých metod) nepoužívá překladač tabulku virtuálních metod a volání je proto o pár nanosekund rychlejší Copyright © 2006, Rudolf Pecinovský VŠE – 05 48

Blue. J a dědění ► Deklaruje se stejně jako implementace rozhraní ● Natažením šipky

Blue. J a dědění ► Deklaruje se stejně jako implementace rozhraní ● Natažením šipky dědění od potomka k rodiči ® Blue. J pak sám upraví hlavičku ● Zápisem hlavičky ® Blue. J pak sám natáhne šipku ► Stejně jako u implementace rozhraní se dědění i ruší ● Smazáním deklarace dědění v hlavičce dosáhneme i odstranění šipky ● Odstraněním šipky dědění dosáhneme i příslušnou změnu v hlavičce ► Definice dědění mezi balíčky/projekty natažením šipky není možná ► Blue. J neumožňuje definovat násobné dědění; definujeme-li natažením šipky dědění od další třídy, Blue. J sám první dědění zruší Copyright © 2006, Rudolf Pecinovský VŠE – 05 49

Třída Čtverec jako potomek třídy Obdélník Copyright © 2006, Rudolf Pecinovský VŠE – 05

Třída Čtverec jako potomek třídy Obdélník Copyright © 2006, Rudolf Pecinovský VŠE – 05 50

Vše ostatní čtverec zdědí Copyright © 2006, Rudolf Pecinovský VŠE – 05 51

Vše ostatní čtverec zdědí Copyright © 2006, Rudolf Pecinovský VŠE – 05 51

Definice třídy Čtverec public class Čtverec extends Obdélník { @Override public void set. Rozměr(

Definice třídy Čtverec public class Čtverec extends Obdélník { @Override public void set. Rozměr( int šířka, int výška ) { super. set. Rozměr( Math. min( šířka, výška ) ); } } ► Definujeme třídu pouze s bezparametrickým konstruktorem, proto jsme definici konstruktoru vynechali ► Všechny metody můžeme zdědit, pouze metodu set. Rozměr(int, int) musíme upravit tak, aby i po její aplikaci zůstal čtverec čtvercem ► V předchozím programu je chyba: definice nepočítá s používáním přetěžujících verzí metod Copyright © 2006, Rudolf Pecinovský VŠE – 05 52

Příčiny chyby v definici třídy Obdélník ► Tvůrce definice si neuvědomil, že: ● Jednoparametrická

Příčiny chyby v definici třídy Obdélník ► Tvůrce definice si neuvědomil, že: ● Jednoparametrická verze public class Obdélník { // Deklarace ostatních //atributů a metod volá dvouparametrickou ● Ta je v potomkovi přebitá, public void set. Rozměr(int rozměr) takže se volá přebíjecí, tj. { potomkova verze set. Rozměr( rozměr, rozměr ); ● Potomkova verze } dvouparametrické metody } volá rodičovskou jednoparametrickou – cyklus je uzavřen public class Čtverec extends Obdélník { @Override public void set. Rozměr( int šířka, int výška ) { super. set. Rozměr( Math. min( šířka, výška ) ); } } Copyright © 2006, Rudolf Pecinovský VŠE – 05 53

Správná definice třídy Čtverec public class Čtverec extends Obdélník { @Override public void set.

Správná definice třídy Čtverec public class Čtverec extends Obdélník { @Override public void set. Rozměr( int šířka, int výška ) { int min = Math. min( šířka, výška ); super. set. Rozměr( min, min ); } } ► Přebíjecí verze potomka volá přebitou verzi rodiče, pouze jí předá upravené hodnoty parametrů, aby i po změně rozměru zůstal čtverec čtvercem ► Mějte na paměti, že podobné podrazy na vás u dědění čekají poměrně často Copyright © 2006, Rudolf Pecinovský VŠE – 05 54

Vaše jistota na trhu IT Podrobnosti o konstruktorech ►Dědění a konstruktory ►Klíčové slovo super

Vaše jistota na trhu IT Podrobnosti o konstruktorech ►Dědění a konstruktory ►Klíčové slovo super ►Na co si dát u konstruktorů pozor ►Obejití virtuální metody v konstruktoru ►Konstruktory × tovární metody ►Konečné třídy 354– 429

Dědění a konstruktory ► Dceřiný konstruktor musí vždy volat rodičovský konstruktor, aby vytvořil potřebný

Dědění a konstruktory ► Dceřiný konstruktor musí vždy volat rodičovský konstruktor, aby vytvořil potřebný rodičovský podobjekt ► Vyhovuje-li volání bezparametrického konstruktoru, nemusí se v definici konstruktoru uvádět ► Potřebujeme-li volat parametrický konstruktor, voláme jej prostřednictvím super následovaného seznamem parametrů ► Dceřiná třída by měla vždy definovat konstruktor maximálně využívající co nejobecnější verzi rodičovského konstruktoru, protože jinak bude pro „vnoučata“ nedostupný public Čtverec( int x, int y, int strana, Barva barva ) { super( x, y, strana, barva ); } Copyright © 2006, Rudolf Pecinovský VŠE – 05 56

Klíčové slovo super ► Volání prostřednictvím super musí být úplně první akcí v těle

Klíčové slovo super ► Volání prostřednictvím super musí být úplně první akcí v těle konstruktoru; nesmí předcházet ani složená závorka ► Stejný požadavek má i volání prostřednictvím this => volání prostřednictvím super a prostřednictvím this se navzájem vylučují public Čtverec() { this( 0, 0 ); } public Čtverec( int x, int y ) { this( x, y, 50, IMPLICITNÍ_BARVA ); } public Čtverec( int x, int y, int strana ) { this( x, y, strana, IMPLICITNÍ_BARVA ); } public Čtverec( int x, int y, int strana, Barva barva ) { super( x, y, strana, barva ); } Copyright © 2006, Rudolf Pecinovský VŠE – 05 57

Viditelnost konstruktorů ► Potomek může používat pouze ty verze rodičovských konstruktorů, na které vidí

Viditelnost konstruktorů ► Potomek může používat pouze ty verze rodičovských konstruktorů, na které vidí ► Třída, která má pouze soukromé konstruktory, nemůže mít žádné potomky ► Nedefinuje-li rodičovská třída dostupný bezparametrický konstruktor, musíme vždy používat volání přes super ► Je-li rodič a potomek ve stejném balíčku, stačí pro rodičovský konstruktor deklarovat implicitní přístup; jsou-li rodič a potomek v různých balíčcích, musí mít rodičovský konstruktor deklarován alespoň chráněný přístup ► Ukázky: viz modrá učebnice a projekt Matka–Dcera–Vnučka Copyright © 2006, Rudolf Pecinovský VŠE – 05 58

Na co si dát u konstruktorů pozor ► V těle konstruktoru nesmíme volat virtuální

Na co si dát u konstruktorů pozor ► V těle konstruktoru nesmíme volat virtuální metody, a to ani zprostředkovaně (tj. volat metodu, která volá virtuální metodu) ● Není to sice syntaktická chyba (bohužel), ale je to poukázka na budoucí problémy ► Pokud potomek danou metodu přebije, může v přebíjecí verzi používat atributy, které při práci rodičovského konstruktoru ještě neexistují (přesněji nejsou ještě inicializovány) ► V konstruktoru bychom proto měli používat pouze soukromé a konečné metody ► Potřebujeme-li použít virtuální (= přebitelnou) metodu, definujeme její soukromou verzi, kterou bude volat jak konstruktor, tak daná virtuální metoda Copyright © 2006, Rudolf Pecinovský VŠE – 05 59

Obejití virtuální metody v konstruktoru ► Po úpravě používá rodičovský konstruktor nepřebitelnou, a proto

Obejití virtuální metody v konstruktoru ► Po úpravě používá rodičovský konstruktor nepřebitelnou, a proto bezpečnou verzi public class Potomek extends Rodič { private final double dělitel=7; private double dělenec; ► Tu vyvolá i nová verze virtuální metody public class Rodič { private double atribut; public class Rodič { } private. Rodič() double {atribut; public atribut=soukromá(); }public Rodič() { atribut=virtuální(); private double soukromá() { } return current. Time. Millis(); }public double virtuální() { return current. Time. Millis(); public double virtuální() { } return soukromá(); } } } Copyright © 2006, Rudolf Pecinovský VŠE – 05 public Potomek(double dělenec) { this. dělenec = dělenec; } @Override public long virtuální() { return dělenec / dělitel; } ► Potomek přebije virtuální metodu vlastní verzí, která vrací podíl svých atributů ► V okamžiku volání rodičem atributy nejsou inicializovány => metoda vrací 0/0 60

Akce před voláním rodičovského konstrukt. ► Občas potřebujeme provést nějakou akci ještě před zavoláním

Akce před voláním rodičovského konstrukt. ► Občas potřebujeme provést nějakou akci ještě před zavoláním rodičovského konstruktoru ► Daný problém je možno řešit dvěma způsoby ● Nečistě: provedením akce v rámci předávání parametrů (stav nejvyššího zoufalství – podrobnosti viz modrá učebnice) ● Lépe: náhradou konstruktoru jednoduchou tovární metodou Ë Tovární metoda je zcela běžná metoda, a proto na ni nejsou kladena omezení platná pro konstruktory ● Může před vlastním voláním konstruktoru cokoliv připravit ● Může se sama rozhodnout, zda vůbec konstruktor zavolá, a pokud ano, tak který konstruktor (třeba i konstruktor potomka) ● Můžeme mít několik různě pojmenovaných (a tím i různě se chovajících) metod se stejnými sadami parametrů Copyright © 2006, Rudolf Pecinovský VŠE – 05 61

Konečné třídy ► Občas potřebujeme zakázat vytváření dceřiných tříd dané třídy ® toho dosáhneme

Konečné třídy ► Občas potřebujeme zakázat vytváření dceřiných tříd dané třídy ® toho dosáhneme modifikátorem final ► Druhou možností je definovat všechny konstruktory soukromé, ale někdy potřebujeme konstruktory zveřejnit ► Takto je ošetřena řada tříd ve standardní knihovně; z dosud probraných tříd jsou to: ● Knihovní třídy (mají navíc soukromé konstruktory) ● Obalové třídy primitivních typů ● String ● Class ► Konečná třída nemůže být zároveň abstraktní Copyright © 2006, Rudolf Pecinovský VŠE – 05 62

Vaše jistota na trhu IT Společný rodič skupiny tříd ►Duplicity v kódu ►Proč společný

Vaše jistota na trhu IT Společný rodič skupiny tříd ►Duplicity v kódu ►Proč společný rodič ►Abstraktní třídy ►Jak vytvořit společného rodiče

Duplicity v kódu – zásada DRY ► Princip DRY (suchá zásada) – Don‘t Repeat

Duplicity v kódu – zásada DRY ► Princip DRY (suchá zásada) – Don‘t Repeat Yourself ► Jednou z věcí, kterých bychom se měli vyvarovat, jsou duplicity v kódu, tj. stejný kód na více místech ► Duplicity v kódu nemusí představovat pouze stejný kód, ale i kód velmi podobný ► Duplicity v kódu lze odstranit několika způsoby ● Duplicity v rámci třídy: definovat metodu a z příslušných míst ji volat ● U duplicitních metod vyskytujících se v několika třídách lze definovat společný kód ve zvláštní třídě a využít návrhového vzoru Služebník ● Jedná-li se o třídy, které jsou všechny speciálním případem čehosi obecnějšího, lze pro ně definovat společného rodiče Copyright © 2006, Rudolf Pecinovský VŠE – 05 64

Proč společný rodič ► Umožňuje soustředit na jedno místo kód, který mohou sdílet všichni

Proč společný rodič ► Umožňuje soustředit na jedno místo kód, který mohou sdílet všichni potomci ► Definuje jednotné rozhraní pro celou skupinu tříd – svých budoucích potomků ► Umožňuje, aby potomci vystupovali jako instance společného rodiče, tj. abychom pro ně mohli definovat společné metody ► Umožňuje deklarovat požadavky (rozhraní) i pro budoucí třídy, které by měly patřit do dané skupiny, tj. pro třídy, které teprve časem vzniknou, ale už nyní víme, jaké by měly mít vlastnosti Copyright © 2006, Rudolf Pecinovský VŠE – 05 65

Abstraktní třídy – proč ► Zatím jsme se seznámili s abstraktními třídami pouze pasivně

Abstraktní třídy – proč ► Zatím jsme se seznámili s abstraktními třídami pouze pasivně jako s hybridy uprostřed mezi klasickými třídami a rozhraními ► Abstraktní třídu můžeme využít tehdy, potřebujeme-li definovat společného předka skupiny potomků avšak některé metody, které by měl tento předek „mít“, v něm nedokážeme implementovat ► Příklad: ● V projektu s plátnem mají všechny obrazce téměř shodné metody => mohli bychom jim tedy definovat společného rodiče ● Některé z těchto metod ale používají metodu nakresli(), pro níž nelze nalézt společnou implementaci – každý ji musí implementovat po svém ● Optimálním řešením je metodu pouze deklarovat (ne definovat), aby ji mohly ostatní metody použít, ale deklarovat ji jako abstraktní a nechat její implementaci na potomcích Copyright © 2006, Rudolf Pecinovský VŠE – 05 66

Abstraktní třídy – shrnutí ► Jakmile třída nějakou metodu neimplementuje, musí deklarovat, že je

Abstraktní třídy – shrnutí ► Jakmile třída nějakou metodu neimplementuje, musí deklarovat, že je abstraktní třídou ► Abstraktní třída se může sama rozhodnout, zda bude metody implementovat, nebo jenom deklarovat ► V definicích implementovaných metod lze použít i volání abstraktních metod, tj. metod, které budou definovat až potomci ► Od abstraktní třídy nelze vytvářet instance ► Třídu lze definovat jako abstraktní, i když vše implementuje, ale my chceme, aby od ní nebylo možno vytvářet instance ► I abstraktní třída musí mít konstruktor, aby mohla vytvářet rodičovský podobjekt v instancích svých potomků ► Abstraktní třída nemůže být konečná Copyright © 2006, Rudolf Pecinovský VŠE – 05 67

Jak vytvořit společného rodiče 1. Projdeme všechny potenciální potomky vytvářeného rodiče a zjistíme, které

Jak vytvořit společného rodiče 1. Projdeme všechny potenciální potomky vytvářeného rodiče a zjistíme, které metody mají společné (nemusí mít stejný kód, musí mít stejný účel) ® to jsou potenciální metody budoucího rodiče 2. Zjistíme, které z nich mají stejný či podobný kód a navrhneme jejich společnou implementaci v rodiči 3. Společné metody, jejichž implementace se ale vzájemně liší, deklarujeme v rodiči jako abstraktní 4. Zjistíme, jaké atributy implementované metody potřebují a deklarujeme je jako atributy rodiče 5. Deklarace a definice všeho, co jsme vystěhovali do rodiče, můžeme v budoucích potomcích smazat Copyright © 2006, Rudolf Pecinovský VŠE – 05 68

Vaše jistota na trhu IT Kdy dědění ano a kdy ne ►Proč nemáme dědění

Vaše jistota na trhu IT Kdy dědění ano a kdy ne ►Proč nemáme dědění rádi ►Kdy použít a kdy nepoužít dědění ►Příklady špatného použití děděníi

Proč nemáme dědění rádi ► Dědění porušuje zapouzdření a skrývání implementace ● Nutí potomka,

Proč nemáme dědění rádi ► Dědění porušuje zapouzdření a skrývání implementace ● Nutí potomka, aby znal implementaci v předku (viz nekonečná smyčka při návrhu metody set. Pozice(int, int)) ● Občas nutí předka, aby znal možné implementace svých potomků ► Dědění zvyšuje vzájemnou provázanost tříd; potřebuji-li modifikovat rodiče (najdu v něm chybu nebo v reakci na změnu zadání), musím zkontrolovat všechny potomky, že tato změna jejich chování nežádoucím způsobem neovlivnila ► Předchozí problém je způsoben tím, že potomek je závislý nejenom na rozhraní rodiče, ale i na jeho implementaci ► Začátečníci jsou možnostmi děděníi unešeni, a často ji proto používají i tam, kam vůbec nepatří Copyright © 2006, Rudolf Pecinovský VŠE – 05 70

Kdy nepoužít dědění ► Vždy, když umím najít jiný rozumný způsob realizace potřebné funkčnosti

Kdy nepoužít dědění ► Vždy, když umím najít jiný rozumný způsob realizace potřebné funkčnosti ● Berme dědění jako KPZ (krabička poslední záchrany) pro případy, které bez ní neumíme dostatečně elegantně vyřešit ● V řadě případů lze dědění výhodně nahradit skládáním, kdy místo dědictví od předka použiji instanci předka jako atribut ► Když potenciální potomek není speciálním případem předka ► Intenzivně uvažujme o NEpoužití děděníi i v případě, když je potomek naopak příliš speciálním případem předka ► Dědění je naopak vhodné použít, když dopředu víme, že potomek je nejenom speciálním případem předka, ale navíc budeme často potřebovat přetypovávat potomka na předka Copyright © 2006, Rudolf Pecinovský VŠE – 05 71

Příklady špatného použití dědění ► Obdélník potomek úsečky, úsečka potomek bodu ► Kruhová výseč

Příklady špatného použití dědění ► Obdélník potomek úsečky, úsečka potomek bodu ► Kruhová výseč je potomkem kruhu ► Kvádr je potomek obdélníku ► Letadlo jako potomek křídla ► Cyklista přeskakující potok po kamenech je potomek žáby ► XObdélník a Terč z modré učebnice ● Zde najdete podrobné vysvětlení, proč je v daném případě použití dědění nevhodné včetně ukázek problémů, k nimž požití dědění v tomto případě vede Copyright © 2006, Rudolf Pecinovský VŠE – 05 72

Vaše jistota na trhu IT Děkuji za pozornost Rudolf Pecinovský http: //vyuka. pecinovsky. cz/vse

Vaše jistota na trhu IT Děkuji za pozornost Rudolf Pecinovský http: //vyuka. pecinovsky. cz/vse mail: rudolf@pecinovsky. cz ICQ: 158 156 600