Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

Polymorfismus Dědičnost

Podobné prezentace


Prezentace na téma: "Polymorfismus Dědičnost"— Transkript prezentace:

1 Polymorfismus Dědičnost
4IT přednáška Polymorfismus Dědičnost

2 Abstraktní datový typ tři vlastnosti ADT: výhody:
lze definovat nové typy a ukrývat reprezentaci těchto typů, lze definovat množinu operací/funkcí s těmito typy ADT je definován v jedné syntaktické jednotce, vytvářet proměnné tohoto typu lze i jinde, výhody: klient není závislý na konkrétní implementaci ADT, klient se nemůže „vrtat“ v ADT – přistupuje pouze prostřednictvím veřejných operací/metod; zvýšená spolehlivost,

3 Objekty požadavky na objekty:
abstraktní datový typ (zapouzdření, ukrývání implementace), třída je typ instance má k sobě přiřazeny datové atributy a metody instance, polymorfismus a pozdní vazba, dědičnost, překrytí metod jednonásobná x vícenásobná dědičnost

4 Pojem polymorfismus polymorfismus – mnohotvarost
biologie: existence několika forem jedinců jednoho druhu nebo populace programování: při stejném volání metody se provádí různý kód. Který kód se provede závisí: na parametrech metod, na instanci (objektu), kterému je zpráva předávána,

5 Typy polymorfismu přetěžování metod (overloading), též ad-hoc polymorphism překrývání metod (overriding), též subtype polymorphism parametrický polymorfismus – např. šablony v C++, parametrický je z toho důvodu, že na základě parametrů se vygeneruje příslušný kód (v C++ se na základě použití šablony generuje kód), často i ve funkcionálních jazycích,

6 Přetěžování metod více metod stejného jména, liší se počtem parametrů,
typem parametrů, pořadím parametrů int nextInt() int nextInt(int n) static String valueOf(double d) static String valueOf(int i) static String valueOf(boolean b) static String valueOf(char c)

7 Překrývání metod Každá třída, která implementuje rozhraní, překrývá všechny metody z rozhraní. Překrývání metod souvisí také s dědičností (viz dále)

8 Příklad: motýli a včely na louce
dvě třídy Motyl a Vcela třetí třída Louka – úkolem je napsat metody pro přidávání motýlů a včel na louku. Máte dva seznamy: varianta 1 – dvě metody různých názvů: public void pridejMotyla (Motyl motyl) { motyli.add(motyl); } public void pridejVcelu (Vcela vcela) { vcely.add(vcela); private List<Vcela> vcely; private List<Motyl> motyli; varianta 1 – nevýhody: duplikuje se informace o tom, zda se předává motýl či včela – je to napsáno nejen v názvu metody, ale i jako typ parametru metody, vytváří se tím velké množství metod s různými názvy, které komplikují použití.

9 Příklad: motýli a včely na louce
2. varianta – jedna metoda s rozskokem dle typu parametru public void pridej (Object o) { if (o instanceof Vcela) { Vcela vcela = (Vcela)o; vcely.add(vcela); } else if (o instanceof Motyl) { Motyl motyl = (Motyl)o; motyli.add(motyl); else { throw new InvallidArgumentException( "lze vkládat pouze motýly a včely"); varianta 2 Metoda je poměrně složitá, je to více řádků kódu, než varianta s přetížením metod, struktura metody je složitější (přibývá rozhodování ohledně typu). Kontrola přípustných typů se přesouvá z doby překladu do běhu aplikace. Překladač povolí, aby parametrem byla instance libovolné třídy (např. String), při běhu však v tomto případě vznikne výjimka. Při použití (tj. při vkládání objektů na louku) by se měl ošetřovat vznik výjimky, tj. vzniká složitější kód i při použití této metody.

10 Příklad: motýli a včely na louce
3. varianta – přetížení metody public void pridej (Vcela vcela) { vcely.add(vcela); } public void pridej (Motyl motyl) { motyli.add(motyl); výhody: zjednodušuje psaní na straně použití, typově bezpečné, omezuje psaní podmínek, jednodušší kód, nevýhody: nelze jednoduše přidávat další typy použití: louka.pridej(new Vcela( )); louka.pridej(new Motyl( ));

11 Příklad: motýli a včely na louce
dvě třídy Motyl a Vcela třetí třída Louka – úkolem je napsat metody pro přidávání motýlů a včel na louku. varianta 4 : ve třídě Louka pouze jeden seznam, použití polymorfismu s využitím rozhraní (interface) – jedna metoda pro přidávání do seznamu, varianta 1 – nevýhody: duplikuje se informace o tom, zda se předává motýl či včela – je to napsáno nejen v názvu metody, ale i jako typ parametru metody, vytváří se tím velké množství metod s různými názvy, které komplikují použití.

12 Deklarace interface [public] interface identifikátor [extends rozhraní1 [, rozhraní2 ...]] { [hlavička_metody1 ;] [hlavička_metody2 ;] … [konstanta1;] [konstanta2;] … [vnořená-třída]….. } obvykle samostatný soubor, všechny metody jsou veřejné (public), všechny konstanty jsou public static konstanty se nedoporučuje v rozhraní používat, modifikátor public nemusí být uveden public interface ObyvatelLouky { public void jednaAkce(); }

13 Implementace rozhraní
public class Motyl implements ObyvatelLouky { public void jednaAkce () { if (naKvetineSNektarem()) { // sbirej nektar } else { preletni(); pokud nějaká metoda z rozhraní není implementovaná, je třída abstrakt metody z rozhraní musí mít modifikátor public stereotyp

14 Rozhraní a subtype polymorfismus (překrývání)
deklarace: private List<ObyvatelLouky> obyvateleLouky; inicializace: obyvateleLouky = new ArrayList<ObyvatelLouky>(); metoda pro vkládání motýlů a včel: public void pridej (ObyvatelLouky obyvatel) { obyvateleLouky.add(obyvatel); }

15 Rozhraní umožňuje volbu implementace
staticky (při překladu) i dynamicky private List <String> slova; v konstruktoru: slova = new ArrayList<String>(); private List <String> slova; v konstruktoru: if (podmínka) { slova = new ArrayList<String>(); } else { slova = new LinkedList<String>(); List je rozhraní, ArrayList a LinkedList implementují rozhraní

16 Rozhraní umožňuje předávat metody jako parametry
příklad rozhraní Comparator a metoda Collections.sort()

17 Dědičnost mezi rozhraními
extends v hlavičce rozhraní

18 Dependency-Inversion Principle
Moduly vyšší úrovně nesmí záviset na modulech nižší úrovně. Oba typy by měli záviset na abstrakci. Abstrakce by neměla záviset na detailech. Detaily obvykle závisí na abstrakci. Pokud modul vyšší úrovně závisí na modulu nižší úrovně, znamená to, že každá změna modulu nižší úrovně ovlivní modul vyšší úrovně. Dependency inversion - obrácení závislostí proti hierarchickému strukturovanému přístupu.

19 Dependency-Inversion Principle

20 Dědičnost v Javě

21 Specializace Při práci s objekty dané třídy č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 atd. Osoby dělíme na muže a ženy 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ě

22 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 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

23 Terminologie Rodičovská třída Bázová třída Nadtřída Dceřiná třída
předek, nadtřída, supertřída potomek, podtřída, překrytí metody, overriding přetížení metody, overloading Dceřiná třída Odvozená třída Podtřída

24 Hierarchie dědičnosti
třídy v Javě mají 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 Na rozdíl od některých jiných jazyků (např. C++) jazyk Java nepodporuje násobnou dědičnost 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

25 Deklarace dědičnosti klíčové slovo extends
v hlavičce třídy public class Liska extends Zvire { …. } public class CD extends AbstractPolozka { … } public class Kniha extends AbstractPolozka implements Comparable { …. } implementace rozhraní se uvádí až za deklarací dědičnosti

26 Definice dědičnosti dědictví od třídy Object se uvádět nemusí, nemá-li někdo v hlavičce uvedeného předka, je přímým potomkem třídy Object třídy z nepojmenovaného (kořenového) balíčku nemají úplný název, a proto nemohou mít potomky v jiných balíčcích

27 Co se vlastně dědí?

28 Co se vlastně dědí? Co znamená výraz, že se něco dědí?
V potomkovi mohu používat prvky předka Když vytvořím instanci potomka, tak mohu používat zděděné metody a atributy předka Potomek obsahuje všechny prvky (metody, atributy) předka

29 Vnučka Dcera Matka Object Aby bylo možno zabezpečit funkci všech (i soukromých) vazeb, obsahuje každý objekt třídy potomka jako svoji součást podobjekt svého předka, Objekt potomka se nemůže začít budovat dřív, než bude zcela vybudován podobjekt předka

30 Postup vytváření instance
Načtou se soubory class do paměti nejdříve se musí načíst soubory .class předka při nahrání souborů .class se inicializují statické prvky, Inicializují se datové atributy Zavolá se a provede konstruktor předka Provede se tělo konstruktoru

31 Co z předka lze používat (volat) v potomkovi?
Datové atributy Metody Konstruktory Statické atributy Statické metody Záleží na modifiká-torech přístupu !!!!

32 Co nabízí potomek ze svého předka?
Záleží na modifikátorech, nesmí být překryté, pozdní vazba Datové atributy Metody Konstruktory Statické atributy Statické metody Záleží na modifikátorech, včasná vazba

33 Final u třídy V hlavičce třídy může být modifikátor final – nemůže mít potomky public final class String extends Object implements Serializable, Comparable<String>, CharSequence

34 Překrývání metod INSTANCí

35 Překrytá metoda v potomkovi je metoda se stejnou hlavičkou (jméno a parametry), jako v předkovi metoda v potomkovi překryla metodu předka

36 Použití překryté verze metody
Překrytí není předefinování ani přepsání překryté metody Při překrytí metody jinou metodou zůstává překrytá metoda nedotčená a můžete ji v potomkovi kdykoliv použít kvalifikace klíčovým slovem super public void metoda() { super.metoda(); …. }

37 Další vlastnosti překrývání metod
Překrývající metoda musí mít stejnou hlavičku (název, počet parametrů a jejich typy, typ návratové hodnoty) jako metoda překrývaná nemá-li metoda stejnou hlavičku, nejedná se o překrytí, ale o přetížení

38 Příklad s účty - dědičnost
Chceme vytvořit účet s možností výběru do mínusu. bude mít stejné proměnné jako třída Ucet a navíc proměnnou limit. musí se změnit metoda pro výběr z účtu.

39 Příklad s účty – dědičnost a zapouzdření
public class Ucet { private int cislo; private String vlastnik; private double stav; public void vloz (double castka) { stav += castka; } public boolean vyber (double castka) {

40 Příklad s účty - dědičnost
public class ZiroUcet extends Ucet { private double limit; public boolean vyber (double castka) { } }

41 Příklad s účty - překrytí metody
public class ZiroUcet extends Ucet { public boolean vyber (double castka) { .... public class Ucet { ...... public boolean vyber (double castka) { ....

42 Příklad s účty - překrytí metody
boolean vyber (double castka) { if (stav < castka) { return false; } else { stav = stav – castka; return true; Ucet.java boolean vyber (double castka) { if ((stav + limit) < castka) { return false; } else { stav = stav – castka; return true; Nepřeloží se, stav je private !!! ZiroUcet.java

43 Příklad s účty – dědičnost a zapouzdření
public class Ucet { private static double urok = 5.2; private int cislo; private String vlastnik; private double stav; public double getStav() { return stav; } public void vloz (double castka) { stav += castka; public boolean vyber (double castka) {

44 Příklad s účty - překrytí metody
boolean vyber (double castka) { if ((getStav() + limit) < castka) { return false; } else { stav = getStav() – castka; return true;

45 Příklad s účty - překrytí metody a zapouzdření
Ucet.java public void setStav (double novyStav){ stav = novyStav; } Možnosti řešení máme možnost změnit třídu Ucet a doplníme do ní metody setStav() nemáme možnost měnit třídu Ucet a musíme nějak použít, to co je. Použijeme metodu vloz() se záporným parametrem. Pokud ale v implementaci tuto možnost třída Ucet neumožní, nejsme schopni dědičnost využít. public boolean vyber (double castka) { if ((getStav() + limit) < castka) { return false; } else { setStav( getStav() – castka); return true; ZiroUcet.java

46 Přetypování referenčních typů, operátor instanceOf

47 Přetypování Přetypování nahoru k předkovi Přetypování dolů
probíhá automaticky instanci jakékoli třídy lze přetypovat na typ Object Přetypování dolů musí být v kódu uvedeno jedná se o návrat k typu, ze kterého proběhlo přetypování směrem nahoru

48 Přetypovávání, operátor instanceOf
public void vypis() { for (Ucet ucet : seznam) { if (ucet instanceof ZiroUcet) { ZiroUcet ziro = (ZiroUcet) ucet; System.out.println(ziro.getVlastnik() + "\tstav: " + ziro.getStav()+"\tlimit: "+ ziro.getLimit()); } else { System.out.println(ucet.getVlastnik() + "\t" + ucet.getStav()); Pokus o přetypování, které nelze provést způsobí ClassCastException ClassCastException je potomkem RuntimeException Překladač není schopen odhalit, zda bude výjimka vyhozena Před přetypováním je možné použít operátor instanceof Vhodnější řešit polymorfismem !!!

49 Dědičnost a KONSTRUKTORY

50 Dědičnost a konstruktory
Konstruktor se nedědí Při spuštění konstruktoru se jako první automaticky volá konstruktor předka, pokud neurčíme který, volá se konstruktor bez parametru. Pro určení volaného konstruktoru předka slouží klíčové slovo super

51 Volání konstruktoru předka, super
public Ucet (int noveCislo, String jmeno, double castka){ cislo = noveCislo; vlastnik = jmeno; stav = castka; } public Ucet (int noveCislo, String jmeno){ stav = 0; Máme několik problémů třída Ucet nemá konstruktor bez parametru i když vytváříme GiroUcet chceme určit číslo učtu, vlastníka a případně i stav účtu, navíc určujeme limit kombinace super a this public ZiroUcet (int noveCislo, String jmeno, double castka, double limit) { super(noveCislo, jmeno,castka); this.limit = limit; }

52 public ZiroUcet (int cisloUctu, String vlastnik,
double pocatecniVklad, double limit){ super(cisloUctu, vlastnik, pocatecniVklad); this.limit = limit; } double pocatecniVklad){ this(cisloUctu, vlastnik, pocatecniVklad, 0); public ZiroUcet (int cisloUctu, String vlastnik){ this(cisloUctu, vlastnik, 0, 0); //volání prvního konstruktoru

53 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) Pokud potomek danou metodu překryje, může v překryvné verzi používat atributy, které při práci rodičovského konstruktoru ještě neexistují (přesněji nejsou ještě inicializovány)

54 Na co si dát u konstruktorů pozor
V konstruktoru bychom proto měli používat pouze soukromé a konečné metody Potřebujeme-li použít virtuální (= překrytelnou) metodu, definujeme její soukromou verzi, kterou bude volat jak konstruktor, tak daná virtuální metoda


Stáhnout ppt "Polymorfismus Dědičnost"

Podobné prezentace


Reklamy Google