1. Dědičnost a polymorfismus

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

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

3. Je defenzivní programování technikou skrývání implementace? Vyberte jednu z nabízených možností: Pravda Nepravda

Třídy. Instance. Pokud tento program spustíme, vypíše následující. car1 má barvu Red. car2 má barvu Red. car1 má barvu Blue.

Dědičnost. seskupování tříd do hierarchie. potomek získá všechny vlastnosti a metody. provádí se pomocí dvojtečky za názvem třídy.

Programování II. Dědičnost změna chování 2018/19

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

1. Programování proti rozhraní

Třída. Atributy. Operace

24. listopadu 2013, Brno Připravil: David Procházka

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

Objekty, třídy, vazby 2006 UOMO 30

Polymorfismus. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 30.března

Abstraktní třída a rozhraní

20. Projekt Domácí mediotéka

Programování v C++ 1, 6. cvičení

Základy objektové orientace I. Únor 2010

10 Balíčky, grafické znázornění tříd, základy zapozdření

Bridge. Známý jako. Účel. Použitelnost. Handle/Body

Dědičnost. Časová náročnost lekce: 3 hodiny Datum ukončení a splnění lekce: 23.března

Chování konstruktorů a destruktorů při dědění

3. Třídy. Základní pojmy objektového programování. Třídy

Programování II. Polymorfismus

OOT Objektově orientované technologie

7.5 Diagram tříd pokročilé techniky

Tento studijní blok má za cíl pokračovat v základních prvcích jazyka Java. Konkrétně bude věnována pozornost rozhraním a výjimkám.

Programování v C++ 3, 3. cvičení

Pokročilé programování v jazyce C pro chemiky (C3220) Dědičnost tříd v C++

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Třídy, polymorfismus. A0B36PR2-Programování 2 Fakulta elektrotechnická České vysoké učení technické

TÉMATICKÝ OKRUH Softwarové inženýrství

7.5 Diagram tříd pokročilé techniky

Dalším příkladem může být například výstup dat na různá zařízení, souborů, grafických rozhraní, sítě atd.

Teoretické minimum z PJV

PŘETĚŽOVÁNÍ OPERÁTORŮ

Programování II. Abstraktní třída Vícenásobná dědičnost 2018/19

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

typová konverze typová inference

7.3 Diagramy tříd - základy

IB111 Programování a algoritmizace. Objektově orientované programování (OOP)

Úvod do programovacích jazyků (Java)

Obsah. October 2, Polymorfizmus. Typologie testování. Problém polymorfizmu. Vady/Anomálie. Vazební sekvence ČVUT FEL, K13132

PB161 Programování v jazyce C++ Přednáška 7

PB161 Programování v jazyce C++ Přednáška 7

7.3 Diagramy tříd - základy

NMIN201 Objektově orientované programování 1 / :36:09

Diagramy tříd - základy

9. Polymorfismus a rozhraní

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Počítačové laboratoře bez tajemství aneb naučme se učit algoritmizaci a programování s využitím robotů CZ.1.07/1.3.12/

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

NPRG031 Programování II 1 / :25:46

Dědění, polymorfismus

Objektově orientované programování v jazyce Python

6 Objektově-orientovaný vývoj programového vybavení

Mnohotvarost (polymorfizmus)

11. Dědičnost. Dědičnost strana 103

Virtuální metody - polymorfizmus

Úvod Třídy Rozhraní Pole Konec. Programování v C# Hodnotové datové typy, řídící struktury. Petr Vaněček 1 / 39

Generické programování

Objektově orientované programování v jazyce Python

Objektové programování

Programování II. Úvod do dědičnosti 2018/19

Výčtový typ strana 67

Návrhové vzory OMO, LS 2014/2015

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

Programování v C++ 2, 4. cvičení

Objekt. základní prvek v OOP. má vlastnosti. má metody. vznikne vytvoření nové instance definován pomocí třídy

Abstraktní třídy, polymorfní struktury

Programování v C++ VI

Infrastruktura UML. Modelování struktury v UML. Superstruktura UML. Notace objektů. Diagramy objektů

Programování II. Návrh programu II

8 Třídy, objekty, metody, předávání argumentů metod

Tvorba informačních systémů

Klíčová slova: OOP, konstruktor, destruktor, třída, objekt, atribut, metoda

Využití OOP v praxi -- Knihovna PHP -- Interval.cz

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

Diagram tříd (class diagram)

Jazyk C# (seminář 3)

Class loader. každá třída (java.lang.class) obsahuje referenci na svůj class loader. Implementace class loaderu

Objektově orientované programování. Úvod

S KONFIGURACÍ POVOLENÝCH KOMBINACÍ DĚDICŮ

Informační systémy 2008/2009. Radim Farana. Obsah. Nástroje business modelování. Business modelling, základní nástroje a metody business modelování.

Jazyk UML - přehled. diagram hierarchie procesů. IS firmy. podpora řízení. evidence zaměstnanců. pokladny. výroba. diagram procesních vláken

Viditelnost (práva přístupu) Tomáš Pitner, upravil Marek Šabo

KTE / ZPE Informační technologie

PB161 Základy OOP. Tomáš Brukner

10 Generické implementace

Jazyk C++ II. Šablony a implementace

Obsah přednášky. 12. Dokumentace zdrojového kódu Tvorba elektronické dokumentace UML. Co je diagram tříd. Ing. Ondřej Guth

4. ZÁKLADNÍ POJMY Z OBJEKTOVĚ ORIENTOVANÉHO PROGRAMOVÁNÍ

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

State. Známý jako. Účel. Použitelnost. Stav, Object for States. umožňuje objektu měnit svoje chování v závislosti na stavu objekt mění svou třídu

Nepravidlové a hybridní znalostní systémy

Funkční objekty v C++.

Jazyk C++ 1. Blok 3 Objektové typy jazyka C++ Třída. Studijní cíl. Doba nutná k nastudování. Průvodce studiem

Seminář Java II p.1/43

PREPROCESOR POKRAČOVÁNÍ

Modelování informačních systémů s využitím jazyka UML. Jaroslav Šmarda

Dědičnost (inheritance)

Transkript:

1. Dědičnost a polymorfismus Cíl látky Cílem této kapitoly je představit klíčové pojmy dědičnosti a polymorfismu. Předtím však je nutné se seznámit se základními pojmy zobecnění neboli generalizace. Komentář V této kapitole se používají dva na první pohled význammově stejné pojmy: operace a metoda. Pojem operace je požíván, když se vysvětlují diagramy tříd UML, zatímco pojem metoda se používá, když se jedná o komentování zdrojových kódů konkrétního programovacího jazyka. 1.1. Zobecnění (generalizace) K správnému pochopení dědičnosti a polymorfismu je nutné získat solidní základy v oblasti zobecnění. Zobecnění je relací mezi obecnějším elementem a elementem přesněji specifikovaným. Přičemž přesněji specifikovaný element je zcela konzistentní s obecnějším elementem, ale obsahuje více informací. Tyto dva elementy se řídí zákonem nahraditelnosti. Konkrétnější element se může použít všude tam, kde by mohl být použít element obecnější, aniž by se ohrozil chod systému.tato relace je mnohem pevnější než je asociace. Odkazy na zákon nahraditelnosti: LSP (EN) [http://www.engr.mun.ca/~theo/courses/sd/pub/sd-principles-3.pdf] LSP (CZ) [http://www.robertdresler.cz/2011/02/liskov-substitution-principle.html] 1.1.1. Zobecnění tříd Z koncepčního hlediska je zobecnění (generalizace) založeno na velice jednoduché myšlence - určitě každý chápe, že zvíře je zobecněním kočky, psa nebo koně. Dokonce zobecnění může být několikaúrovňové. Z předchozího příkladu se můžou pes a kočka považovat za domácí zvířata a ty například s volně žijícími zvířaty se teprve mohou zevšeobecnit do zvířat. 1

Obrázek 1.1. Hierarchie zobecňovaní Na obrázku 1.1 je třída Zvíře zcela určitě obecný pojem. Od tohoto pojmu jsou odvozeny potomci, podtřídy, které jsou specializovanými variantami obecného pojmu Zvíře. Podle zákona o nahraditelnosti lze použít jakékoliv potomky tříd Kočka, Pes nebo Kůň kdekoli, kde lze použít třídu Zvíře. Když se postupuje od konkrétního k obecnějšímu, je tento myšlenkový postup nazýván právě zobecňováním, ale lze postupovat i opačným směrem, to je od obecnějšího ke konkrétnějšímu, potom tento postup se nazývá specializace. Někdy se tyto dva pojmy spojují do slangového slova genspec. Při návrhu objektově orientovaného softwaru se používají metody, jak postupného zobecňování, tak metodu postupného upřesňování. 1.1.2. Dědičnost tříd Při uspořádání tříd do hierarchie zobecnění tak, jak je znázorněno na obrázku 1.1 se vytvoří dědičná vazba mezi třídami, v níž potomci dědí všechny charakteristické vlastnosti svého předka neboli nadtřídy. Jsou to: Atributy, operace, relace. Potomci mohou ke zděděnému fondu vlastností přidat novou charakteristiku. Ale nejen to, mohou dokonce některé operace předefinovat. Překrývání Z diagramu 1.2 lze odečíst, že podtřídy Čtverec a Kruh dědí všechny atributy, operace z nadtřídy Tvar. Charakteristiku nadtřídy Tvar v podtřídách není vidět, přesto je v těchto podtřídách implicitně obsažena. Tomu se říká, že třídy Čtverec a Kruh jsou typu Tvar. 2

Obrázek 1.2. Diagram tříd s dědičností Diagram 1.2 je sice v pořádku, ale takto navržený systém by správně nefungoval, protože operace kreslit() operace nadtřídy nic neví o svých podtřídách, jak by měla vykreslit podtřídy Čtverec nebo Kruh. To samé platí pro operace vypočtiobsah() a vypočtiobvod(). V případě podtřídy Kruh dokonce nadtřída nemůže ani vědět, že třída Kruh obsahuje atribut poloměr. Z předchozího jasně vyplývá, že potomci musí být schopni změnit implicitní chování svých rodičů. Třídy Čtverec a Kruh nutně musí implementovat vlastní operace kreslit(), vypočtiobsah() a vypočtiobvod(), které překrývají implicitní operace svého předka. Tyto operace se již mohou postarat o správnější chování. Následující diagram 1.3 již jasně demonstruje, že operace předka jsou překryty příslušnými operacemi potomků. 3

Obrázek 1.3. Překrytí operací předka Potomci překrývají (mění definici) zděděných operací tím, že definují novou operaci se stejnou signaturou. Programovací jazyky mohou signaturu operace definovat odlišným způsobem. Například v jazycích C++ a Java sice není návratový typ operace součástí signatury operace, ale přesto jej při překrývání je nelze změnit. Pokud dojde k překrytí operace předka operací potomka, která se liší návratovým typem, ohlásí překladač chybu. Abstraktní operace a třídy Někdy je zapotřebí odložit implementaci operace a přenechat ji potomkům nadtřídy. Například operace Tvar::kreslit() je ideální ukázkou tohoto případu. V třídě Tvar nelze vytvořit žádnou smysluplnou implementaci zmiňované operace, protože se neví jaký tvar se má vykreslit. Pojem vykreslit tvar je příliš abstraktní, než aby se mohl nějak uchopit jakoukoliv konkrétní implementací. Když je zapotřebí určit, že operace postrádá implementaci, definuje se jako abstraktní. V jazyce UML se to vyjadřuje tím, že název operace se napíše kurzivou. 4

Obrázek 1.4. Abstraktní třída a operace Jakmile je ve třídě alespoň jedna operace abstraktní, je taková třída neúplná a proto z ní nelze vytvořit instanci. Takové třídy se označují jako abstraktní. Pro název takové třídy platí v UML stejné pravidlo, jako u abstraktní operace. Název je zapsán zase kurzívou. Dokonce platí takové pravidlo, že pokud je třída označená jako abstraktní a současně nemá žádnou abstraktní operaci, nelze z této třídy vytvořit instanci. Třídy, které umožňují tvorbu svých instancí, se obecně označují jako třídy konkrétní (instanční). Užití abstraktních tříd a operací má nesporně dvě velké výhody: 1. Množinu abstraktních operací lze definovat v abstraktní nadtřídě, která musí být implementována všemi svými potomky. Tento postup lze považovat za definici určité dohody, kterou konkrétní potomci musí implementovat. 2. Může se vytvořit kód, který manipuluje se všemi potomky dané nadtřídy podle zákona nahraditelnosti. Tyto výhody jsou stěžejními principy polymorfismu, kterému je věnována další kapitola. Stupně abstrakce Předměty na stejné úrovni zobecnění by se měly vyznačovat stejným stupněm abstrakce. 5

Příklad zdrojového kódu Výpis 1.1. Abstraktní třída Tvar public abstract class Tvar { protected Bod počátek = (0,0); protected int šířka; protected int výška; public abstract void kreslit(); public abstract float vypočtiobsah(); public abstract float vypočtiobvod(); Uvedením modifikátoru abstract před klíčovým slovem třídy class se vytváří abstraktní třídu. Z této třídy nelze vytvořit instanci. Atributy třídy Tvar jsou všechny označeny modifikátorem protected, aby bylo možné k nim přistupovat z potomků. Není to nejlepší řešení, protože se tím odkrývá implementace třídy Tvar. Tomuto problému je věnováno jedno z dalších témat. Jestliže se modifikátor abstract uvede v deklaraci metody, je potom tato metoda abstraktní, proto chybí tělo metody. Výpis 1.2. Konkrétní třída Kruh public class Kruh extends Tvar { private int poloměr; public Kruh(Bod b, int r){ počátek = b; poloměr = r; public void kreslit(){... public float vypočtiobsah(){ return (float) (Math.PI*poloměr*poloměr); public float vypočtiobvod(){ return (float)(2*math.pi*poloměr); Protože u atributu počátek je modifikátor protected, lze k němu přistupovat z potomka. Není to dobré řešení. Správnější by bylo, aby tento atribut byl privátní a jeho nastavení by mělo být zabezpečeno pomocí parametru konstruktoru předka. Tělo metody kreslit() je zde vynecháno z důvodu zjednodušení a protože se nevztahuje k samotné problematice abstraktních tříd. Všechny metody v konkrétní třídě, které překrývají abstraktní metody zděděné od všech svých předků, musí mít definovány konkrétní těla metod. 6

1.2. Polymorfismus Polymorfismus znamená mnohotvarost. Polymorfní operace jsou operace s mnoha implementacemi. V příkladu třídy Tvar to byly všechny tři abstraktní operace, protože tyto operace mají v každém potomku jiné implementace. Operace tedy mají mnoho forem a jsou proto polymorfní. Třídy Čtverec a Kruh z diagramu 1.4 dědí od třídy Tvar a poskytují implementace polymorfním operacím Tvar::kreslit(), Tvar::vypočtiObsah() a Tvar::vypočtiObvod(). Všichni potomci třídy Tvar musí poskytovat konkrétní operace kreslit(), vypočtiobsah() a vypočtiobvod(), neboť tyto operace jsou deklarovány v nadtřídě. To znamená, že z pohledu operací kreslit(), vypočtiobsah() a vypočtiobvod()se může se všemi potomky třídy Tvar jednat stejně. Množina abstraktních operací je tedy způsobem, jak definovat množinu operací, které musí implementovat všichni konkrétní potomci. Podstata polymorfismu - objekty různých tříd obsahují operace se stejnou signaturou, ovšem s jinou implementací. 1.2.1. Příklad polymorfismu Na diagramu 1.5 je třída KreslicíPlátno, která vlastní kolekci objektů typu Tvar. Že se jedná o kolekci je znázorněno hvězdičkou u šipky na konci čáry, která definuje asociaci mezi třídami KreslícíPlátno a Tvar. Takto, i když je to velmi zjednodušeno, pracuje většina grafických systémů. Obrázek 1.5. Příklad diagramu tříd s polymorfismem Třída Tvar je abstraktní a proto nemůže z této třídy vzniknout žádná instance. Podle zákona o nahraditelnosti, lze však vytvářet instance z konkrétních potomků, které lze dosazovat všude tam, kde je volána třída Tvar. Na diagramu 1.6 je ukázka možného objektového modelu, který vznikl podle diagramu tříd 1.5. Objektový model ukazuje, že objekt :KresliciPlatno 7

obsahuje čtyři spojení na objekty t1, t2, t3 a t4. Objekty t1, a t3 jsou instancemi třídy Kruh a objektyt2 a t4 jsou instancemi třídy Čtverec. K čemu dojde, když objekt :KreslícíPlátno projde svoji kolekci? Každý takto vyvolaný objekt provede přesně to co je od něho očekávano. Objekt typu Kruh vykreslí kruh a objekt typu Čtverec vykreslí čtverec. Obrázek 1.6. Příklad diagramu objektů z diagramu tříd1.5 Podtržení v objektovém diagramu 1.6 signalizuje, že se jedná o objekt. Podobný účel má dvojtečka před typem objektu. 8