15. díl - Rozhraní (interface) v Javě

Java Objektově orientované programování Rozhraní (interface) v Javě

V minulém dílu seriálu tutoriálů o Javě jsme si procvičili práci s kolekcí ArrayList při tvorbě elektronického diáře. Dnes to bude opět trochu teoretické, objevíme další taje objektově orientovaného programování, uvedeme si totiž rozhraní.

Rozhraní

Rozhraním objektu se myslí to, jak je objekt viditelný zvenku. Již víme, že objekt obsahuje nějaké metody, ty mohou být privátní nebo veřejné. Rozhraní objektu tvoří právě jeho veřejné metody, je to způsob, jakým s určitým typem objektu můžeme komunikovat. Již jsme se s ním několikrát setkali, např. u našeho bojovníka do arény. Třída Bojovnik měla následující veřejné metody:

  • void utoc(Bojovnik souper)
  • void branSe(int uder)
  • boolean nazivu()
  • void nastavZpravu(String zprava)
  • string vratPosledniZ­pravu()
  • string grafickyZivot()

Pokud si do nějaké úproměnné uložíme instanci bojovníka, můžeme na ni volat metody jako utoc() nebo branSe(). To pořád není nic nového, že?

My si však rozhraní můžeme deklarovat zvlášť a to podobným způsobem jako třeba třídu. Toto rozhraní poté použijeme jako datový typ.

Vše si vyzkoušíme, ale na něčem jednodušším, než je bojovník. Vytvořme si nový projekt a nazvěme ho Rozhrani. Přidáme si nějakou jednoduchou třídu. Protože by se dle mého názoru měla teorie vysvětlovat na něčem odlehčujícím, uděláme si Ptáka. Bude umět pípat, dýchat a klovat. Přidejme si třídu Ptak, bude vypadat takto:

public class Ptak
{

        public void pipni()
        {
                System.out.println("♫ ♫ ♫");
        }

        public void dychej()
        {
                System.out.println("Dýchám...");
        }

        public void klovni()
        {
                System.out.println("Klov, klov!");
        }

}

Třída je opravdu triviální. Přejděme do Rozhrani.java a vytvořme si instanci ptáka:

Ptak ptak = new Ptak();

Nyní napíšeme ptak. a necháme NetBeans, aby nám zobrazil metody na třídě (lze také vyvolat stiskem ctrl + space):

Metody ptáka

Vidíme, co na ptákovi můžeme vše volat, jsou tam samozřejmě ty 3 metody, co jsme ve třídě implementovali (plus další, které mají objekty v základu).

Nyní ptákovi vytvoříme rozhraní. Využijeme k tomu klíčového slova interface (anglicky rozhraní). Pojmenování rozhraní v Javě je poměrně věda, my se spokojíme s názvem PtakInterface. Pravým tlačítkem klikneme na projekt, a přidáme nový item - Interface.

Nový interface v NetBeans pro Javu

K projektu se nám přidá prázdný interface. Do něj přidáme hlavičky metod, které má dané rozhraní obsahovat. Samotnou implementaci (kód metod) uvedeme až ve třídě, která bude toto rozhraní implementovat (viz dále).

Do rozhraní PtakInterface tedy přidáme hlavičky metod, schválně jednu vynecháme a přidáme pouze Pípání a Dýchání:

public interface PtakInterface
{
        void pipni();
        void dychej();
}

Modifikátor public neuvádíme, protože rozhraní obsahuje vždy pouze veřejné metody (jinak by nemělo smysl, udává, jak s objektem zvenku pracovat).

Vraťme se do Rozhrani.java a změňme řádek s proměnnou ptak tak, aby již nebyla typu Ptak, ale PtakInterface:

PtakInterface ptak = new Ptak();

Kódem výše říkáme, že v proměnné typu PtakInterface očekáváme objekt, který obsahuje ty metody, co jsou v rozhraní. NetBeans nám vyhubuje, protože třída Ptak zatím rozhraní PtakInterface neobsahuje, i když potřebné metody má, neví, že rozhraní poskytuje. Přesuneme se do třídy Ptak a nastavíme jí, že implementuje interface PtakInterface. Dělá se to klíčovým slovem implements:

public class Ptak implements PtakInterface
{
 . . .

Když se nyní vrátíme do Rozhrani.java, řádek s proměnnou typu PtakInterface je již v pořádku, třída Ptak korektně implementuje rozhrani PtakInterface a její instance může být do proměnné tohoto typu uložena.

Zkusme nyní vymazat ze třídy nějakou metodu, kterou rozhraní udává, třeba pipni(). NetBeans nás upozorní, že implementace není kompletní. Vraťme ji zas zpět.

Opět přidáme řádek ptak., NetBeans nám nabídne následující metody:

Metody ptáka s rozhraním PtakInterface

Vidíme, že od instance můžeme nyní očekávat pouze to, co poskytuje rozhraní. To proto, že proměnná ptak je již typu PtakInterface, nikoli Ptak. Metoda klovni() úplně chybí.

K čemu je to dobré? Výhod a využití je více, na první jsme již přišli. Pomocí rozhraní dokážeme zjednodušit rozhraní nějakého složitého objektu a vystavit jen tu část, která se nám v tu dobu hodí.

Ještě dodám, že nemůžeme vytvořit instanci z rozhraní, tento kód nebude fungovat:

// tento kód nebude fungovat
PtakInterface ptak = new PtakInterface();

Vícenásobná dědičnost

Java (stejně jako většina jazyků) nepodporuje vícenásobnou dědičnost. Nemůžeme tedy jednu třídu oddědit z několika jiných tříd. Je to hlavně z toho důvodu, že může vyvstat problém kolize názvů metod v různých třídách, ze kterých dědíme. Vícenásobná dědičnost se často obchází právě přes interface, protože těch můžeme ve třídě implementovat kolik chceme. Umožňuje nám to s instancí poté pracovat určitým způsobem a vůbec nás nezajímá, jakého typu objekt ve skutečnosti je a co všechno navíc obsahuje.

Přidejme si k projektu interface JesterInterface. Bude to interface ještěra. Ten bude umět také dýchat a ještě se plazit:

public interface JesterInterface
{
        void plazSe();
        void dychej();
}

Vyzkoušejme si "vícenásobnou dědičnost", přesněji implementaci více rozhraní v jedné třídě. Udělejme si ptakoještěra. Přidejme k projektu třídu PtakoJester. Bude implementovat rozhraní PtakInterface a JesterInterface:

public class PtakoJester implements JesterInterface, PtakInterface
{
}

Když nyní klikneme na ikonu žárovky, můžeme v kontextovém menu zvolit možnost Implement all abstract methods. NetBeans nám automaticky do třídy vygeneruje potřebné metody.

Automatická implementace rozhraní v NetBeans

Po implementaci obou rozhraní vypadá kód třídy takto:

public class PtakoJester implements JesterInterface, PtakInterface {

    @Override
    public void plazSe() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void dychej() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void pipni() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}

Všimněte si, že NetBeans přidal notaci @Override k metodám, které implementují rozhraní. Je to tak přehlednější a @Override si připíšeme i k metodám pipni() a dychej() v třídě Ptak.

Metody v ještěrovi doimplementujeme:

@Override
public void plazSe()
{
        System.out.println("Plazím se...");
}

@Override
public void dychej()
{
        System.out.println("Dýchám...");
}

@Override
public void pipni()
{
        System.out.println("♫ ♫♫ ♫ ♫ ♫♫");
}

Přesuňme se do Rozhrani.java a vytvořme si instanci ptakoještěra:

PtakoJester ptakojester = new PtakoJester();

Ujistěme se, že má metody jak ptáka, tak ještěra:

Metody ptáka a ještěra

Příště budeme pokračovat v podobném duchu, rozhraní ještě neopustíme a naučíme se další pokročilé techniky objektově orientovaného programování.


 

Stáhnout

Staženo 354x (16.71 kB)
Aplikace je včetně zdrojových kódů v jazyce java

 

  Aktivity (1)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (4 hlasů) :
55555


 



 

 

Komentáře

Avatar
Kit
Redaktor
Avatar
Kit:

Ještě tam chybí poznámka, že rozhraní se dá využít k vytváření objektů anonymních tříd.

PtakInterface ptak = new PtakInterface();

sice fungovat nebude, ale po doplnění metod

PtakInterface ptak = new PtakInterface() {

    @Override
    public void pipni() {
        System.out.println("♫ ♫ ♫");
    }

    @Override
    public void dychej() {
        System.out.println("Dýchám...");
    }

    @Override
    public void klovni() {
        System.out.println("Klov, klov!");
    }
};

z toho bude hezký anonymní objekt.

Odpovědět  +1 30.4.2013 10:50
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Kit
David Čápka:

Díky, anonymní třídy mám v plánu v dalších dílech, s trochou štěstí bych mohl tento týden dopsat sekci s OOP v Javě.

Odpovědět  +1 30.4.2013 10:58
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
domino.turak
Člen
Avatar
domino.turak:

Ešte ja mám otázku že prečo môže byť VtakoJaster vtakoJaster=new VtakoJaster() ale napríklad VtakInterface vtak=new VtakInterface() byť nemôže?

Odpovědět 23.6.2013 0:24
"Never give up!"
Avatar
Kit
Redaktor
Avatar
Odpovídá na domino.turak
Kit:

Protože v interface chybí implementace deklarovaného rozhraní. Můžeš ji doplnit při vytváření instance. Nemůžeš však použít konstruktor.

VtakInterface vtak = new VtakInterface() {
   // tady můžeš napsat implementaci
}

EDIT: Teď koukám, že jsem to už napsal o pár řádek výš. Četl jsi to vůbec?

Editováno 23.6.2013 2:37
Odpovědět 23.6.2013 2:35
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
domino.turak
Člen
Avatar
Odpovídá na Kit
domino.turak:

Jáááj áno už mi to je jasné :) Áno čítal som, stále čítam všetky komentáre pod každým článkom, avšak ty si písal niečo o anonymných objektoch, tak som si to až teraz uvedomil že to čo som sa pýtal ja si už vlastne vysvetlil vyššie :-P V každom prípade ďakujem za odpoveď :)

Odpovědět 23.6.2013 13:22
"Never give up!"
Avatar
Iwitrag
Člen
Avatar
Iwitrag:

Ahoj,

mám malý dotaz.

Kdybychom u PtakoJestera měli ještě nějakou jinou zděděnou metodu, kterou bychom nechtěli implementovat, jak by se to udělalo?

Datový typ můžeme použít jen od jednoho rozhraní (buď PtakInterface nebo JesterInterface) i navzdory tomu, že třída implementuje obě rozhraní naráz, a když použijeme dat. typ PtakoJester, tak budeme mít k dispozici všechny metody (i zděděné které třeba nechceme)...

Odpovědět 16.1.2014 18:24
Učím se ostře vidět.
Avatar
Hartrik
Redaktor
Avatar
Odpovídá na Iwitrag
Hartrik:

U klasické třídy musí být vždy implementované všechny metody. Teoreticky by situace, kterou popisuješ neměla nastat - pokud by např. PtakoJester nemohl implementovat metodu klovni nebo vzletni, tak se nejedná o ptáka a PtakInterface se nepoužije.

 
Odpovědět 17.1.2014 14:29
Avatar
roman64
Redaktor
Avatar
roman64:

Ahoj,
asi tomu úplně nerozumím. Při vícenásobné dědičnosti jde přeci o to, aby PtakoJester zdědil medoty tříd Ptak a Jester. V uvedem prikladu jsme ale dosahli pouze toho, že tyto metody (předků Ptak a Jester) přepíšeme (překryjeme) novým kódem (viz. throw new UnsupportedOpe­rationExcepti­on("Not supported yet."). Ty metody, které NetBeans nabízí u instance ptakoJester jsou metody třídy PtakoJester (přepsané metody potomka) a nikoliv zděděné metody předků Ptak a Jester. Nebo se pletu?

Odpovědět 3.7.2015 8:31
osvícený člověk se učí celý život, hlupákovi stačí hodina
Avatar
martin kubin
Člen
Avatar
martin kubin:

zaujimalo by ma ako to je v praxi co sa tyka rozhrania.samotny clanok o rozhrani chapem,ked mam proste dve triedy napr Vtak a Jaster a chem spravit dalsiu odvodenu z tych dvoch ,napr VtakoJaster,tak si spravim z oboch rozhrania htore potom implementujem v triede VtakoJaster,sprav­ne?

Ale povedzme ze mam triedu Zviera s nejakou metodou public void dychat(),potom mam dalsia dve triedy ako v priklade hore,triedu Vtak a Jaster,oboje dedenia z triedy Zviera.A teraz chcem opat vytvorit triedu VtakoJaster.ako to byva v praxi?Zase si len vytvorim rozhrania z tried Vtak a Jaster a implementujem ich do VtakoJastera?Ma nejaky vyznam napr triedu VtakoJaster dedit zo Zvierata+imple­mentovat rozhrania VtakInterface a JasterInterface alebo dokonca ze by Vtakojaster dedil napr z triedy Vtak a mal iba jedno rozhranie z Jastera?
mozno to pisem moc komplikovane a mozno v tomto pripade to ani nehra velku rolu ale co sa pouziva v praxi ked tych tried je viac a tie su odvodene z dalsich tried atd

 
Odpovědět 30.7.2015 17:13
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.