Java interface tajemství zbavený


Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /data/www/15070/dadajax_net/www/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /data/www/15070/dadajax_net/www/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /data/www/15070/dadajax_net/www/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /data/www/15070/dadajax_net/www/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

Je to asi rok, kdy jsem se začal učit objektově orientovanému programování. Tehdy jsem byl v zaměstnání donucen naučit se OOP principům a to hlavně v Javě. Vzpomínám si, jaké problémy mi dělalo, než jsem pochopil význam a použití rozhraní (interface) v Javě. Tento článek je tedy zamýšlen jako taková pomůcka, která by měla objasnit používání rozhraní a to hlavně začátečníkům. Pro pochopení tohoto článku byste měli zvládat minimálně základy v Javě. Nenechte se zmást, v článku budu používat slova rozhraní i interface, které zde mají stejný význam.

Co to ten interface tedy je?

Začnu z té technické stránky věci. V Javě existují klasické třídy, abstraktní třídy a rozhraní. Zde je jejich popis:

  • Normální třída: je to ta třída, která nemá žádný z níže uvedených modifikátorů. Všechny metody, které tato třída má, mají svou implementaci. To znamená, že už obsahují kód, který něco dělá.
  • Abstraktní třída: je to třída, která má modifikátor abstract. To znamená, že chování některých metod nemusí tato třída implementovat. V tom případě může být implementace těchto metod přenechána třídám, které tuto třídu rozšiřují (dědí z ní, neboli jsou jejími potomky).
  • Rozhraní: má modifikátor interface. Rozhraní neobsahuje žádnou implementaci. Definují pouze metody, které ale neobsahují žádný kód.

(jak jsem byl upozorněn v komentáři pod článkem, abstract a interface nejsou modifikátory viz tento komentář. Až na zmatení pojmu jsou ale výše uvedené tvrzení správné :))

Proč tedy vzniklo v Javě rozhraní? Jedním z důvodů byla skutečnost, že v Javě neexistuje vícenásobná dědičnost. Třída může mít pouze jednoho předka (to znamená, že může rozšířit pouze jednu třídu). Toto omezení má své důvody (vícenásobná dědičnost může způsobovat problémy). Použití rozhraní ve třídě označujeme jako „třída implementuje rozhraní“.

Uvedu příklad:

public interface Zobrazovac {
    void ukazZpravu(String zprava);
}

Jak vidíte, rozhraní Zobrazovac má pouze jednu metodu. Tato metoda má jeden parametr, který obsahuje textový řetězec. Podle názvu si domyslíme, co tato metoda dělá. Netušíme ale, jakým způsobem to dělá a co k tomu používá. To ani vědět nechceme. Chceme jen uživateli zobrazit zprávu, víc nás nezajímá. Nyní je třeba vytvořit nějakou třídu, která bude toto rozhraní implementovat. Pro jednoduchost vytvoříme třídu TextovyZobrazovac, která zprávu zobrazí v konzoli.

public class TextovyZobrazovac implements Zobrazovac {
   // Zde je implementace metody ukazZpravu z rozhrani Zobrazovac.
    void ukazZpravu(String zprava) {
        // Vytiskneme zpravu na konzoli.
        System.out.println(zprava);
    }
}

Teď si asi říkáte, proč to dělat tak složitě. Vždyť bychom se bez toho rozhraní obešli a ušetřili bychom si čas. Teď si ale představte, že budete chtít zprávu zobrazit nejen do konzole, ale i do souboru a v některých případech zprávu zobrazit jako formátovánou HTML stránku. Kdyby nebylo vytvořeno rozhraní Zobrazovac, museli byste vytvořit několik tříd, které by se staraly o různé způsoby zobrazení zprávy. Při jejich použití v programu byste ale museli vědět, co to jsou za třídy, jaké metody pro zobrazení zprávy používají a případně znát další detaily.

V našem případě jsme si ale zavedli rozhraní Zobrazovac a tudíž můžeme ve svém kódu vytvořit třeba pole typu Zobrazovac, do kterého budeme ukládat jednotlivé zobrazovače, které mají být aktivní. V případě potřeby potom projedeme všechny prvky tohoto pole a zavoláme nad nimi metodu ukazZpravu(). Víme totiž, že všechny instance (různých) tříd v poli implementují Zobrazovac, tudíž tuto metodu mají. Nemusíme se tedy starat o to, jaké třídy vlastně máme, víme jen, že umí zobrazit nějakým způsobem zprávu.

Příklad ze života

Pokusím se princip rozhraní vysvětlit na nějakém příkladu ze života. Vemte si třeba počítačovou myš. Žádnou konkrétní, jen si představte zjednodušený model myši. Představte si myš jako rozhraní, které nám poskytuje kliknutí levým tlačítkem a kliknutí pravým tlačítkem. Dejme tomu, že toto je základní rozhraní pro všechny myši. Když se naučíte toto rozhraní, budete umět ovládat všechny myši, které mají toto rozhraní. Bude vám jedno, jestli bude myš plastová, nebo kovová. Optická nebo kuličková. Modrá nebo bílá. Kulatá nebo hranatá. Vám stačí jen vědět, že s ní můžete provést klik levým, nebo pravým tlačítkem.

Tyto dvě tlačítka jsou tedy rozhraní myši a vám je upřímně jedno, co se při stisku tlačítka děje. Neřešíte, jak to uvnitř myši funguje – jestli jsou tam nějaké mechanické části, nějaké optické čidla, nebo skřítci, kteří sledují pohyb tlačítka. Stejně je to i s rozhraním v Javě. Na úrovni rozhraní nevidíte dovnitř – nevíte jak se daná úloha provede.

Teď si představte, že se vám do ruky dostane nějaká herní myš, která bude krom hlavních dvou tlačítek obsahovat desítky dalších tlačítek a koleček. I přesto ale budete tuto myš schopni ovládat, protože pořád implementuje rozhraní klasické myši – má přeci levé a pravé tlačítko. Zbytek vás v danou chvíli nezajímá. Stejně i v našem příkladě nás nezajímá, co všechno třída TextovyZobrazovac všechno umí. Stačí jen vědět, že implementuje rozhraní Zobrazovac, díky kterému ji můžeme používat pro naše účely.

Ukažme si tedy příklad s myšmi v Java kódu:

/**
 * Rozhraní klasické myši. Jen dvě tlačítka, které lze stisknout.
 */
public interface KlasickaMys {
    void kliknutiLevymTlacitkem();
    void kliknutiPravymTlacitkem();
}
 
/**
 * Tato myš je úplně obyčejná myš, která nemá žádné funkce navíc.
 */
public class UplneObycejnaMys implements KlasickaMys {
    void kliknutiLevymTlacitkem() {
        // Zde bude napsaný kód, který se provede při stisku levého tlačítka.
        // Tato metoda je implementací metody z rozhraní KlasickaMys
    }
    void kliknutiPravymTlacitkem() {
        // Zde bude napsaný kód, který se provede při stisku pravého tlačítka.
        // Tato metoda je implementací metody z rozhraní KlasickaMys
    }
}
 
/**
 * Tato myš má v sobě zabudovanou lampičku.
 */
public class MysSLampickou implements KlasickaMys {
 
    void kliknutiLevymTlacitkem() {
        // Zde bude napsaný kód, který se provede při stisku levého tlačítka.
        // Tato metoda je implementací metody z rozhraní KlasickaMys
    }
    void kliknutiPravymTlacitkem() {
        // Zde bude napsaný kód, který se provede při stisku pravého tlačítka.
        // Tato metoda je implementací metody z rozhraní KlasickaMys
    }
    void rozsvitLampicku() {
        // Jak vidíte, toto je funkce navíc, kterou klasické myši nemají.
    }
}

Tak a teď zkusíme tyto myši použít. Vytvoříme třídu Uzivatel, která bude obsahovat pole s objekty implementujícími interface KlasickaMys. Nejdříve toto pole naplníme nějakými objekty a následně projedeme všechny prvky pole a otestujeme na nich klepnutí na levé a pravé tlačítko.

public class Uzivatel {
 
     private KlasickaMys[] poleMysi;
 
      /**
      * V konstruktoru vytvoříme instance několika myší, které má uživatel
      * k dispozici, aby je poté mohl vyzkoušet.
      */
     public Uzivatel() {
         // Vytvoření pole, do kterého umístíme dvě různé myši, které budou implementovat interface KlasickaMys
         poleMysi = new KlasickaMys[2];
 
         // Přidáme do pole s myšmi obyčejnou myš.
         KlasickaMys mys1 = new UplneObycejnaMys();
         poleMysi[0] = mys1;
 
         // Přidáme do pole s myšmi myš s lampičkou.
         KlasickaMys mys2 = new MysSLampickou();
         poleMysi[1] = mys2;
     }
 
     /**
      * Této metodě předáme v parametru jakýkoliv objekt, který implementuje interface KlasickaMys.
      * Díky tomu víme, že můžeme otestovat stisk levého a pravého tlačítka. To co se po kliknutí
      * stane už záleží na konkrétní implementaci. U myši s lampičkou zde ale nemůžeme otestovat
      * funkci rozsvitLampicku(), protože není obsažená v rozhraní KlasickaMys.
      */
     public void otestujMys(KlasickaMys mysNaOtestovani) {
         mysNaOtestovani.kliknutiLevymTlacitkem();
         mysNaOtestovani.kliknutiPravymTlacitkem();
     }
 
     /**
      * V této metodě si uživatel zkusí u každé myši uložené v poli poleMysi
      * kliknutí levým i pravým tlačítkem.
      */
    public void vyberMys() {
        for (int i = 0; i < poleMysi.lenght; i++) {
            otestujMys(poleMysi[i]);
        }
    }
 
}

Když pak vymyslíme nějakou novou, lepší myš, jednoduše vytvoříme instanci nové myši a vložíme ji do pole s myšmi. Nemusíme už tedy měnit žádné další části programu, protože každá myš, která implementuje rozhraní KlasickaMys bude umět pořád ten stejný základ – kliknutí levým a pravým tlačítkem.

Tak jako ve skutečném světě, i ve svém programu byste měli skrývat detaily o implementaci. U myši taky určitě nechcete vědět, co všechno se děje při stisku tlačítka. Nechcete zkoumat při koupi nové myši, jak se ovládá. Chcete nějaké jednotné rozhraní, které bude společné pro všechny myši. I u auta vás bude zajímat především jeho rozhraní. Když sednete do nového auta a bude mít stejné rozhraní (volant, pedály…), budete ho umět ovládat. Teď si ale představte, že byste sedli do nového auta a tam by místo volantu a pedálu byl umístěn knipl jako v letadle. Toto auto by neimplementovalo rozhraní klasického auta a proto byste ho museli používat zcela jinak než klasické auta.

Shrnutí

Jak vidíte, používání rozhraní přináší mnohé výhody. I když to zpočátku vypadá, že používat rozhraní je zbytečná práce navíc, není to tak. Pokud se budete snažit používat rozhraní co nejvíce, uvidíte, že si ušetříte spoustu času. Jakmile zjistíte na vlastní kůži ty výhody, určitě začnete rozhraní používat pravidelně.

Pokud vám přiložené příklady nestačily, na internetu najdete určitě spoustu dalších příkladu. Další možná ukázka rozhraní je při použití Observeru (Observer, Listener…to jsou slova které si zkuste vyhledat). Po přečtení tohoto článku si zkuste vymyslet nějaké další příklady, kde by bylo vhodné použít rozhraní. Zkuste si tyto příklady převést do kódu a naprogramovat to.

Pokoušel jsem se článek napsat co nejjednodušeji. Pokud se vám ale bude zdát něco nesrozumitelné, budu velmi rád, když mě na to upozorníte v komentáři pod článkem.

Příspěvek byl publikován v rubrice Programování. Můžete si uložit jeho odkaz mezi své oblíbené záložky.

39 komentářů: Java interface tajemství zbavený

  1. David Nogol napsal:

    Uff, konečně. Článek mírně upraven. Snad už nedostanu chuť to překopat 😀 http://tinyurl.com/crb74v

  2. Luba napsal:

    Výborný a srozumitelný článek napsaný lidovou řečí a praktický, perfektně vysvětlený příklad. Článek mi jakožto zelenáčovi v Javě hodně pomohl a autorovi za něj děkuji.

  3. dadajax napsal:

    Děkuji za pochvalu. Jsem rád, že článek splnil svůj účel a dokázal problematiku rozhraní trochu objasnit 🙂

  4. Miky napsal:

    Přidávám se k pochvale! Snad se konečně podaří napsat tu písemku 🙂 Díky.
    Jen bych možná trochu upřesnil jednu větu:“Víme totiž, že všechny třídy v poli implementují Zobrazovac,…“ na „Víme totiž, že všechny instance (různých) tříd v poli implementují Zobrazovac,…“. Možná se ale pletu.

  5. dadajax napsal:

    Miky: děkuji za pochvalu a za opravení, samozřejmě že máš pravdu. Blbě jsem to napsal 🙂 Hned to opravím

    Tak hodně štěstí u té písemky 😉

  6. MK napsal:

    Děkuji a zdravím ze studijního pobytu ze španělska, kde jsem interface nepochopil v angličtině a snažil se najít srozumitelné vysvětlení v českém jazyce. A našel jsem 🙂

  7. dadajax napsal:

    MK: jsem rád že článek pomohl 🙂 Posílám pozdrav do Španělska 😉

  8. root napsal:

    Skutecne velmi srozumitelne. Dik moc.

  9. rudyment napsal:

    Drobná korekce: interface není modifikátor, ale určení druhu datového typu. Kdyby to byl modifikátor, muselo by se psát

    public interface class

    Java prostě zavádí tři druhy datových typů: class, enum a interface. Druh class pak má navíc poddruh abstract class.

  10. rudyment napsal:

    Je-li tu víc takových, kteří trochu tápou s významem a používáním rozhraní, tak jsem včera odevzdal do nakladatelství CP učebnici programování, v jejímž prvním dílu se vůbec nevykládá dědičnost tříd, ale veškerý výklad je postavený na používání rozhraní.

    Rukopis četlo asi 10 lidí, kteří se přihlásili na výzvu v konferencích, a všichni si jej chválili. Tak možná pomůže i některým tápajícím.

    Tento text má svůj anglický protějšek na stránkách Sunu. Teď jej ale předělávám, tak zatím ani neříkám adresu.

  11. dadajax napsal:

    Rudymet: Děkuji za opravení, článek opravím.

  12. MK napsal:

    2 rudiment:
    chtěl jsem se zeptat, za jak dlouho myslíš, že by ta učebnice mohla vyjít? a ve španělsku asi dostupná moc nebude, co? myslíš, že by byla nějaká možnost dostat se k tomu rukopisu? jde o to, že by se mi tady hodilo něco o JAVĚ v CZ… neříkám, že články na internetu jsou špatné, ale přece jenom by to chtělo něco ucelenějšího…
    díky za odpověď…

  13. Kamilos napsal:

    Zdravím,

    díky za článek. Pro začátečníky je určitě vhodný, ale nemůžu si odpustit malou výtku. V příkladu se objevuje:

    UplneObycejnaMys mys1 = new UplneObycejnaMys();

    ale mělo by být
    KlasickaMys mys1 = new UplneObycejnaMys();

    jde o detail ale, začátečníci by se to měli učit už od začátku správně. Kolirát vidím u pokročilých programátorů jak píší
    HashSet s = new HashSet()
    namísto
    Set s = new HashSet()

    a je to proto, že ani kvalitní knížky pro začátečníky tohle nezdůrazňují!

  14. dadajax napsal:

    Kamilos: děkuji za upozornění. Opraveno 😉

  15. Uf napsal:

    Ahoj, jeste upresneni:
    Slovo ROZHRANI (angl. INTERFACE) ma dva vyznamy:
    1) obecny, ktery oznacuje seznam toho, co objekt umi – tedy zkracene seznam metod, public memberu. Seznam vsech metod, tedy i zdedenych od predku a implementovanych rozhrani. 2) abstraktni datovy typ (ADT) ve smyslu, v jakem je popisovan v clanku.

    Pekny clanek. Zvlastni, ze nekdo pise verejne po roce a nekdo ani po letech. Uf.

  16. dadajax napsal:

    Uf: Ahoj, děkuji za doplnění 😉 Chtěl jsem využít toho, že mám ještě v živé paměti ty své začátky a pamatuju si na ty problémy, které jsem tehdy měl. Tomu jsem se snažil přizpůsobit i ten styl psaní a ty zvolené příklady. Čím více toho ale vím, tím více mi přijde absurdní, jak jsem něco podobného nemohl pochopit 🙂

  17. Mato napsal:

    Ja sa len chcem opytat ci
    private KlasickaMys[] poleMysi; by nemalo byt staticke:private static KlasickaMys[] poleMysi; pretoze bez toho mi nepojde metoda OtestujMys….

  18. dadajax napsal:

    Mato: nevidím důvod, proč by mělo bát poleMysi statické. Co to znamená, že ti bez toho nepůjde metoda otestujMys?

    Metodu otestujMys musíš volat nad nějakou instancí třídy Uzivatel. Děláš to?

  19. Mato napsal:

    No ano ze musim to nad niecim volat but ….

    Uzivatel Mato = new Uzivatel();
    Mato.otestujMys(poleMysi[0]);//tu mi pise error ze cannot make a static reference to the non-static field poleMysi a funguje to ked tam hodim static lenze to dost meni potom tuto triedu

  20. dadajax napsal:

    poleMysi je privátní atribut třídy Uzivatel. Nemůžeš jej tedy používat z vnějšku třídy Uzivatel. Pokud chceš zavolat metodu otestujMys, tak musíš ještě vytvořit krom instance třídy Uzivatel taky instanci nějaké třídy, která dědí z rozhraní KlasickaMys.

    Takže v tvém případě:
    Uzivatel Mato = new Uzivatel();
    Mato.otestujMys(new UplneObycejnaMys() );

  21. mato napsal:

    diki moc uz to ide …

  22. David42 napsal:

    Nějak se mi rozhraní nedaří pochopit stále. Připadá mi to, že je to jen proto, že když implementuji nějaké rozhraní, tak nesmím zapomenout na ty metody které jsou v rozhraní napsané. Je to tak?

  23. dadajax napsal:

    David42: není. Pokud ti rozhraní stále nedává smysl ani po přečtení tohoto článku, zkoušej číst dál z jiných zdrojů. Doporučuji třeba knihu Návrhové vzory.

    Každému sedne jiné vysvětlení, takže musíš jen hledat dokud nenajdeš nějakou definici nebo příklad, ze kterého ti to pak bude jasné 🙂

  24. uf napsal:

    David42: v podstate ano. Ty poskytnes funkcionalitu pro objekty, ktere maji urcite vlastnosti (rozhrani) a uzivatel tvych objektu jen doda vlastni implementaci.

    Navic to krasne oddeli implementaci sluzby (tve knihovny) a objektu, ktere ji mohou pouzivat. Knihovna se odvolava JEN na vlastnosti (metody), ktere potrebuje pro svou funkcionalitu, a ostatni umeni ji nezajima.

    Resi to i vicenasobnou dedicnost, ktera muze prinest problemy, ale je treba ji pouzit hlavne pri analyticke nutnosti.

  25. Dawe napsal:

    Mohl by mi prosim nekdo vysvetlit jaky je hlavni rozdil mezi Abstract a interface? Porad mi to neni uplne jasny… Musim udelat Abstraktni seznam v Jave a nejsem si jist, zda je potreba vyuzit Interface nebo zda si vystacim pouze s Abstract … Predem diky za odpoved!

  26. rudyment napsal:

    Interface je čistá deklarace bez jakékoliv implementace. On jenom deklaruje svoje pžadavky na třídy, které jej následně implementují.

    Třída, byť abstraktní, vždy nějakou implementaci má. Dokud se obejdeš bez implementace, jelepší používat interface. Jakmile potřebuješ, aby se něco implementovalo, musíš sáhnout po třídě.

    Při definici abstraktního seznamu vystačíš s interfacem do té doby, dokud bude stačit, že jenom deklaruješ, co musí takový seznam umět. (Takto se chová např. interface List ze standardní knihovny.) Jakmile budeš muset naprogramovat i nějaké konkrétní chování, musíš sáhnout po třídě (viz AbstractList, resp. AbstractSequentialList v Javě)-

  27. Dawe napsal:

    Diky za rychlou odpoved! Uz mi to je snad jasny 🙂

  28. uf napsal:

    Ahoj. Abstraktni trida uz implementuje nejake chovani. Muze jit o zakladni tridu urcenou k dedeni, pricemz jeji instance analyticky nema vyznam.
    Jde o to, ze implementujes zakladni chovani a nektere speciality – abstraktni metody – MUSI implementovat tva trida.
    Abstraktni trida muze mit i svou metodu, kde se volaji jednotlive kroky scenare. Nektere kroky jsou povinne naprogramovany (private metoda), nektere lze prekryt (protected) a nektere lze (public) nebo se MUSI (abstraktni) implementovat. Takze muzes napr. prekryt u komponenty compActivated(), ale musis prekryt compPersist() nebo buildGUI().

  29. uf napsal:

    Takze muzes implementovat algoritmus s povinnymi a nepovinnymi kroky

  30. rudyment napsal:

    V říjnu se ptal MK, kdy vyjde ona učebnice. Trochu se to protáhlo – mylslel jsem původně, že vyjde v listopadu, ale měli někde v redakci uzel, takže vyšla až na přelomu února a března. Kdyby si jí chtěl někdo pustit přes palec a podívat se, jak se dají rozhraní vysvětlovat a jak se s nimi dá pracovat, te se jmenuje

    „OOP – Naučte se myslet a programovat objektově“

  31. Jozef napsal:

    Chcem poďakovať za článok. dobre som pochopil čo to interface je :-), skvele je napísaný .
    Aj ked mi unika jeho použitie, ale ako písal autor, to sa dozviem v praxi.
    Teraz pri písaní mi to došlo. ako autor písal, je to náhrada za mnohonásobnú dedičnosť :-).

  32. uf napsal:

    Hlavni je urcit rozhrani (umeni tridy, deklarovat metody) tak, aby pouziti nejake funkcnosti nebylo zavisle na konkeretni implementaci.

    Je pravda, ze v podstate predepisu abstraktniho predka.

  33. Yemi napsal:

    Cau chtel bych se zeptat, jaky je rozdil mezi: KlasickaMys mys1 = new UplneObycejnaMys();

    a UplneObycejnaMys mys1 = new UplneObycejnaMys(); ??

    a

    public void otestujMys(KlasickaMys mysNaOtestovani) {
    mysNaOtestovani.kliknutiLevymTlacitkem();
    mysNaOtestovani.kliknutiPravymTlacitkem();

    }
    kdyby zde vytvoril instance tridy te rozsirenejsi mysi a zadal to jako parametr teto metody tak jak se dostanu k metode rozsvitLampicku, kdyz v te metode neni deklarovana? diky predem

  34. Jan napsal:

    Dobrý den,

    celkem dobře napsáno, ale hapruje mi tam přesně to na co se ptá Yemi. Jak z tohoto použiji ty rozšiřující metody, které jsou v dalších myších?

    // v objektu mys2 tu rozšiřující třetí metodu nezískám
    MouseClicks mys2 = new AdvanceMouse();
    poleMysi[1] = mys2; // moznosti pouze leve a prave tlacitko

    to bych musel vytvořit objekt přímo z AdvanceMouse
    AdvanceMouse am = new AdvanceMouse();
    am.kliknutiProstrednimTlacitkem(); // toto je ta třetí metoda – prostredni tlacitko

  35. rudyment napsal:

    Loňský dotaz Yemiho mi utekl, tak odpovím až nyní.

    Interface deklaruje, co musejí umět instance třídy, která se rozhodne jej implementovat. Co umějí navíc není z hlediska příslušného rozhraní zjímavé. Třída, která implementuje rozhraní, tím zabezpečí, že se její instance mohou vydávat za instance daného rozhraní (něco jako když se ve filmu Vrchní prchni Abrhám vydával za vrchního).

    Interface KlasickáMyš deklaruje, co musejí umět všechny myši, které se chtějí vydávat za klasickou myš. Když definuji metodu s parametrem typu KlasickáMyš, je mi jedno, jaká bude daná myš ve skutečnosti, protože vím, že mi stačí, že se mohu spolehnout na to, že umí reagovat na stisk levého a pravého tlačítka (takže např. původní myš Applu, která měla jediné tlačítko, by zde použít nešla).

    Kdybych potřeboval třítlačítkovou myš, musel bych si pro ni definovat nové rozhraní, které by bylo potomkem předchozího (aby se ona třítlačítková myš mohla vydávat za klasickou) a které by navíc deklarovalo metodu pro reakci na stisk třetího tlačítka.

    Za třítlačítkovou myš by se pak mohly vydávat všechny myši, které mají alespoň tří tlačítka.

    S podrobnějším výkladem bych opět odkázal na knihu „OOP – Naučte se myslet a programovat objektově“, o níž jeden recenzent prohlásil, že z ní musí OOP pochopit každý, kdo umí číst.

  36. Jan napsal:

    Děkuji,

    ono je to důležité doplnit o tu dědičnost. Rozhraní může dědit z více dalších rozhraní. Tím nám vznikne už nějaká stromová struktura rozhraní.

    V tom příkladu ale stále nechápu jaký význam část v konstruktor Uzivatel, kde

    // Přidáme do pole s myšmi myš s lampičkou.
    KlasickaMys mys2 = new MysSLampickou();
    poleMysi[1] = mys2;

    Toto přece je zbytečné ne? Jak a pro co se to dá použít?

  37. rudyment napsal:

    První věcí je, že bych v daném případě nepoužil pole, ale seznam. V případě pole totiž musím dopředu vědět, kolik v něm těch myší bude a nemohu proto přidávat za chodu další. Tento problém u seznamu odpadá.

    Daný příklad se snaží ukázat, že se všemi instancemi implementujícími dané rozhraní se dá pracovat stejně. To právě ukazují následující dvě metody. Prví testuje myš zadanou v parametru, přičemž metodu vůbec nazajímá, co je to ve skutečnosti za myš. Pro ni je to prostě klasická myš a jako takovou ji testuje.

    No a druhá metoda projde všechny uložené myši a každou z nich předá té první k otestování. Takže jak se vám bude rozšiřovat sbírka vašich myší, budete je postupně přidávat do pole (nebo podle mne do seznamu) a můžete je pak hromadně testovat.

    Takto by se zdálo, že má smysl otestovat pouze poslední myš, protože ty starší už jsou otestované. Jenomže stejně jako můžete rozšiřovat sbírku myší, tak můžete vylepšovat i test a doplnit jej např. o test dvojkliku nebo současného stisku levého a pravého tlačítka. No a pak se vám hodí metoda, která vezme ze seznamu postupně jednu myš za druhou a každou prožene upraveným testem.

  38. Jan napsal:

    jj děkuji,

    právě máme na interface a ArralyList školení. Chce to zažít v praxi a používat interface právě kvůli budoucím rozšíření.

    Děkuji
    S pozdravem
    Jan

  39. Gregor napsal:

    Este by som doplnil, ako to cele spustit, tiez som tomu velmi nerozumel. 🙂 Dik

    public class Test {

    public static void main(String[] args){

    Uzivatel zobraz = new Uzivatel();
    zobraz.vyberMys();
    }

    }

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.