1 / 49

4IT101 8.přednáška

4IT101 8.přednáška. Polymorfismus Dědičnost. Abstraktní datový typ. tři vlastnosti ADT: 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,

kamil
Download Presentation

4IT101 8.přednáška

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 4IT101 8.přednáška Polymorfismus Dědičnost

  2. Abstraktní datový typ • tři vlastnosti ADT: • 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++,

  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;

  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"); } }

  10. Příklad: motýli a včely na louce 3. varianta – přetížení metody publicvoid pridej (Vcela vcela) { vcely.add(vcela); } publicvoid pridej (Motyl motyl) { motyli.add(motyl); } použití: louka.pridej(new Vcela( ...... )); louka.pridej(new Vcela( ...... )); louka.pridej(new Motyl( ...... )); 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,

  12. Deklarace interface [public] interfaceidentifikátor [extendsrozhraní1 [, rozhraní2 ...]] { [hlavička_metody1 ;] [hlavička_metody2;] … [konstanta1;] [konstanta2;] … [vnořená-třída]….. } public interface ObyvatelLouky { public void jednaAkce(); }

  13. Implementace rozhraní public class Motyl implements ObyvatelLouky { public void jednaAkce () { if (naKvetineSNektarem()) { // sbirej nektar } else { preletni(); } } }

  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>(); }

  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.

  19. Dependency-Inversion Principle

  20. Dědičnost v Javě

  21. Terminologie • Rodičovská třída • Bázová třída • Nadtřída • Dceřiná třída • Odvozená třída • Podtřída

  22. 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 Objectmá 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

  23. Deklarace dědičnosti • klíčové slovo extends • v hlavičce třídy public classLiskaextendsZvire{ …. } public class CDextendsAbstractPolozka { … } public class KnihaextendsAbstractPolozka implements Comparable { …. } • implementace rozhraní se uvádí až za deklarací dědičnosti

  24. 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

  25. Co se vlastně dědí?

  26. 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

  27. 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

  28. 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

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

  30. 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

  31. Final u třídy • V hlavičce třídy může být modifikátor final – nemůže mít potomky public finalclassStringextendsObjectimplementsSerializable, Comparable<String>, CharSequence

  32. Překrývání metod INSTANCí

  33. 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

  34. 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 voidmetoda() { super.metoda(); …. }

  35. 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í

  36. Příklad s účty - dědičnost • Chceme vytvořit účet s možností výběru do mínusu. • budemí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.

  37. Příklad s účty – dědičnost a zapouzdření public classUcet{ privateintcislo; privateString vlastnik; privatedouble stav; public void vloz (double castka) { stav += castka; } public booleanvyber (double castka) {....... } ............................................................................... }

  38. Příklad s účty - dědičnost public classZiroUcetextendsUcet{ privatedouble limit; public booleanvyber (double castka) { .......... } .............. }

  39. 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

  40. 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í metodysetStav() • 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

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

  42. Přetypování • Přetypování nahoru k předkovi • 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

  43. Přetypovávání, operátor instanceOf public void vypis() { for (Ucetucet : seznam) { if (ucetinstanceofZiroUcet) { ZiroUcetziro = (ZiroUcet) ucet; System.out.println(ziro.getVlastnik() + "\tstav: " + ziro.getStav()+"\tlimit: "+ ziro.getLimit()); } else { System.out.println(ucet.getVlastnik() + "\t" + ucet.getStav()); } } } Vhodnější řešit polymorfismem !!!

  44. Dědičnost a KONSTRUKTORY

  45. 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

  46. 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){ cislo = noveCislo; vlastnik = 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 public ZiroUcet(intnoveCislo, String jmeno, double castka, double limit){ super(noveCislo, jmeno,castka); this.limit = limit; }

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

  48. 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)

  49. Na co si dát u konstruktorů pozor • V konstruktoru bychom proto měli používatpouze 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

More Related