Abstraktní třída a rozhraní Někdy se může stát, zejména při psaní v hierarchické struktuře hodně nadřazených tříd, že tušíme, že bude ve zděděných třídách vhodné použít nějakou metodu. Tuto metodu ještě nemůžeme napsat, ale můžeme si vynutit ve zděděné třídě její naprogramování použitím klíčového slova abstrakt u metody v rodičovské třídě. public abstract class Zivocich private int hmotnost; private int vek; public Zivocich(int m, int v) hmotnost = m; vek = v; public Zivocich() hmotnost = 0; vek = 0; // metody set, get pro hmotnost, vek public abstract String kdojsem(); public abstract String ozvise(); public class Pes extends Zivocich private String jmeno; private String rasa; public Pes(int m, int v, String jm, String rasa) super(m,v); jmeno = jm; this.rasa = rasa; public Pes() super(); jmeno = "Vorisek"; rasa = "smeska"; // metody set, get, tostring() public String kdojsem() return "Pes"; public String ozvise()
return "Vrrr, haf, har!"; public class Ryba extends Zivocich private String druh; private boolean morska; public Ryba(int m, int v, String d, boolean voda) super(m,v); druh = d; morska = voda; public Ryba() super(); druh = "ryba"; morska = false; // metody set, get, tostring() public String kdojsem() return "Ryba"; public String ozvise() return "Šplouch"; Třída Zivocich musí být abstraktní, jakmile totiž v naší třídě použijeme alespoň jednu abstraktní metodu, pak nelze vytvořit instanci třídy a z toho důvodu je celá třída označena jako abstraktní. Polymorfismus Polymorfismus dovoluje manipulovat s prvky příbuzného, ale předem neznámého typu. Základní trik polymorfismu je v tom, že potomek může nahradit předka. To prakticky znamená, že do referenční proměnné typu předka můžeme přiřadit referenci na instanci potomka. Využití abstraktní třídy Použijeme abstraktní třídu Zivocich a třídy Pes a Ryba, z příkladu na abstraktní třídy. public static void main(string[] args) List<Zivocich> list = new ArrayList<Zivocich>(); list.add(new Pes()); list.add(new Ryba(6,2,"kapr",false)); for (int i = 0; i < list.size(); i++) System.out.println(list.get(i).ozviSe());
Do pole nebo ArrayListu typu Zivocich můžeme ukládat objekty tříd Pes i Ryba, aniž bychom měli tušení, o kterou instanci se jedná. Při zavolání metody ozvise() bude díky polymorfismu použita správná metoda. Příklad: (příklad napište v jazycích Java i Csharp) Vytvořte třídu reprezentující obecný obrazec se souřadnicemi středu, obvodem a plochou a na jejím základě definujte třídy pro kruh, obdélník a čtverec. Uložte kruhy, obdélníky i čtverce do společného ArrayListu. Vypište na obrazovku jejich polochu a obvod. Rozhraní Java neumožňuje vícenásobnou dědičnost (třída vznikne děděním z více rodičovských tříd najednou). Jako částečnou náhradu má Java možnost používat rozhraní. Rozhraní definuje soubor metod, které v něm ale nejsou implementovány tj. obsahuje pouze hlavičky metod, stejně jako je tomu u abstraktní metody. Třída, která toto rozhraní implementuje (jakoby zdědí), musí překrýt všechny jeho metody. Rozhraní není totéž jako abstraktní třída: - Nemůže deklarovat žádné proměnné jenom konstanty - Třída může implementovat více než jedno rozhraní - Rozhraní je nezávislé na dědičné hierarchii tříd (naprosto odlišné třídy mohou implementovat stejné rozhraní) Konstrukce rozhraní Zápis rozhraní se podobá zápisu třídy: public interface Obrazec public double obvod(); public double obsah(); Použití rozhraní Každá třída, která implementuje rozhraní, musí uvést jeho jméno v hlavičce za klíčovým slovem implements. public class Kruznice implements Obrazec private int polomer; public Kruznice(int r) polomer = r; public String tostring()
return "Kruznice o polomeru "+polomer; public double obsah() return 2*Math.PI*polomer; public double obvod() return Math.PI*polomer*polomer; public class Obdelnik implements Obrazec private int a; private int b; public Obdelnik(int x, int y) a = x; b = y; public String tostring() return "Obdelnik o stanach "+a+" a "+b; public double obsah() return a*b; public double obvod() return 2*(a+b); public double uhlopricka() return Math.sqrt(a*a + b*b); Jistě nás nepřekvapí, že metody obsah() a obvod() jsou standardní metody obou tříd, bylo však nutné je implementovat. Pouze abstraktní třída si může dovolit implementovat rozhraní bez toho, aby se v ní naprogramovala i těla metod z rozhraní. Pokud je rozhraní nějakou třídou implementováno, lze deklarovat referenční proměnnou typu rozhraní, pomocí které lze přistupovat k instancím všech tříd, které rozhraní implementují. public static void main(string[] args) Obrazec obr; obr = new Kruznice(5);
Obrazec[] pole = new Obrazec[2]; pole[0] = new Kruznice(4); pole[1] = new Obdelnik(4,5); System.out.println("Obvod prvniho obrazce je "+pole[0].obvod()); // pouze metoda Obelnika, nutno napred objekt pretipovat double uhl = ((Obdelnik)pole[1]).uhlopricka(); Pomocí referenční proměnné typu rozhraní můžeme přistupovat pouze k metodám, které jsou v něm uvedeny (viz. metoda uhlopricka()). Implementované rozhraní se dědí beze změny. Metody rozhraní budou přístupné i v odděděné třídě a bude se jednat o tytéž metody (pokud je překryjeme). Polymorfismus Polymorfismus dovoluje manipulovat s prvky příbuzného, ale předem neznámého typu. Základní trik polymorfismu je v tom, že potomek může nahradit předka. To prakticky znamená, že do referenční proměnné typu předka můžeme přiřadit referenci na instanci potomka. Příklad 1: (Vypracujte v jazyce Java i Csharp) Vytvořte rozhraní, které bude obsahovat abstraktní metodu vydejzvuk(), metoda nebude mít vstupní parametry a bude vracet String. Dále vytvořte třídu Pes, která bude jako vlastnosti obsahovat jako vlastnosti rasu psa, jeho jméno a věk. Pro třídu napište alespoň 3 konstruktory, zapouzdřete vlastnosti třídy a do třídy implementujte vaše rozhraní (metoda vydejzvuk bude vracet Haf, haf, haf!! ). Poté vytvořte třídu Kocka, která bude obsahovat jako vlastnosti rasu kočky, její jméno a věk. Pro třídu napište konstruktor, vlastnosti třídy zapouzdřete a do třídy implementujte vaše rozhraní (metoda vydejzvuk bude vracet Mnau, mnau!! ). V metodě main vytvořte ArrayList, do kterého budete moci vkládat jak kočky, tak psy. Uložte do něj několik prvků a pak vypište na obrazovku, jaké zvuky budou jednotlivá zvířata uložená v listu vydávat. Příklad 2: (Vypracujte v jazyce Java i Csharp) Vytvořte třídu Student, která bude mít jako vlastnosti jméno a příjmení studenta a jeho datum narození. Dále vytvořte třídu Trida, která bude obsahovat seznam studentů. Ve třídě Trida vytvořte metodu, která bude umět setřídit seznam studentů podle příjmení (mají-li dva studenti stejné příjmení, provnejte je ještě podle křestního jména).