NOVINKA: Získej 40 hodin praktických dovedností s AI – ZDARMA ke každému akreditovanému kurzu!
S účinností od 26. 3. jsme aktualizovali Zásady zpracování osobních údajů – doplnili jsme informace o monitorování telefonických hovorů se zájemci o studium. Ostatní části zůstávají beze změn.

Diskuze – Lekce 18 - Rozhraní (interface) v Javě

Zpět

Upozorňujeme, že diskuze pod našimi online kurzy jsou nemoderované a primárně slouží k získávání zpětné vazby pro budoucí vylepšení kurzů. Pro studenty našich rekvalifikačních kurzů nabízíme možnost přímého kontaktu s lektory a studijním referentem pro osobní konzultace a podporu v rámci jejich studia. Toto je exkluzivní služba, která zajišťuje kvalitní a cílenou pomoc v případě jakýchkoli dotazů nebo projektů.

Komentáře
Avatar
Odpovídá na Ondřej Havlíček
Petr Štechmüller:23.6.2023 17:44

Ahoj, zkusím to vysvětlit kompletně mimo kontext článku.

Řekněme, že máme rozhraní Auto. Aut může být několik značek (tříd implementující rozhraní Auto): "Skoda", "Audi", "Citroen".

Rozhraní Auto bude mít jednu metodu maximalniRychlost(), která vrátí maximální rychlost auta.

Dále budeme mít speciální třídu reprezentující továrnu na auta TovarnaAut, která bude vytvářet auta pomocí metody vytvorAuto(String typAuta). Návratový typ této metody bude rozhraní Auto, protože tebe jako uživatele pak nezajímá konkrétní implementace rozhraní, ale pouze metody, které to rozhraní poskytuje.

Takže pak by kód vypadal přibližně takto:

TovarnaAut tovarnaAut = new TovarnaAut();
Auto skoda = tovarnaAut.vytvorAuto("Skoda");
Auto audi = tovarnaAut.vytvorAuto("Audi");

int maxRychlostSkody = skoda.maximalniRychlost();
int maxRychlostAudi = audi.maximalniRychlost();

...

Myšlenka je taková, že v reálném projektu se neprogramuje vůče konkrétním třídám, ale vůči rozhraní, přičemž neřešíš, jaká je implementace rozhraní.

Proto až budeš probírat kolekce tak zjistíš, že existuje rozhraní List, které je implementováno různými třídami: ArrayList a LinkedList. Obě třídy poskytují implementaci metod z rozhraní List, jen trochu jinak.

Odpovědět
23.6.2023 17:44
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Odpovídá na Petr Štechmüller
Ondřej Havlíček:23.6.2023 18:34

Uff, no, abych pravdu řekl, pořád tomu teda nerozumím. Buď mi chybí ještě nějaký kus látky a nebo mám zkrátka o kolečko míň.

V článku bylo psáno, že rozhraní nejde instanciovat - nejde založit konstruktor. Jak je tedy možné, že bude metoda vytvorAuto() (která je ve třídě TovarnaAut) vracet instanci rozhraní Auto?
Navíc, metody nemůžou mít body (tělo), jak pak může metoda maximalniRychlost() rozhraní Auto, vracet nějakou hodnotu?

Nevím, jestli toho po Tobě nebudu chtít moc, ale mohl bys, prosím, nastínit kompletní funkční kód Tebou navrženého příkladu výše?

Editováno 23.6.2023 18:37
 
Odpovědět
23.6.2023 18:34
Avatar
Odpovídá na Ondřej Havlíček
Petr Štechmüller:23.6.2023 19:38

To je právě to kouzlo rozhraní. Nemusíš vědět, jak instance vznikla (nemusíš znát implementaci). Stačí ti jen, že to dělá to, co potřebuješ.

Kdybychom se ale podívali "pod pokličku" na implementaci metody vytvorAuto(), mohla by vypadat nějak takhle:

Auto vytvorAuto(String typAuta) {
switch (typAuta) {
        case "Skoda": return new Skoda();
        case "Audi": return new Audi();
    }
}

Syntaxe nemusí přesně odpovídat, nejsem na PC.

Odpovědět
23.6.2023 19:38
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Atrament
Člen
Avatar
Odpovídá na Ondřej Havlíček
Atrament:24.6.2023 13:23

U interface(rozhraní) je potřeba pochopit, že nejde o dědičnost v pravém slova smyslu, třída implementující nějaké rozhraní od toho rozhraní nic nedědí, ta třída se naopak zavazuje k tomu že sama implementuje metody specifikované v rozhraní. To je ten hlavní rozdíl oproti dědičnosti, kde naopak třída která dědí od nějaké jiné třídy, doopravdy dědí už existující funkčnost. U použití interface se správně tedy nemluví o dědičnosti ale o kompozici (skládání).

Dále je třeba pochopit, že v příkladu co uváděl Petr Štechmüller ta tovární metoda má sice návratovou hodnotu typu Auto, ale to nemusí být nutně zároveň typ instance, kterou vracíš pomocí return. Stačí právě, že bude typu, který implementuje interface Auto, takže to může být Skoda nebo Audi, tak jak je to v tom příkladu. V něm se vrací instance konkrétního typu Skoda nebo Audi podle vstupního parametru, ale my si ji uložíme do instance obecného typu Auto, protože je nám jedno jakého konkrétního typu je, my budeme pracovat pouze s metodama definovanýma v rozhraní Auto.

Dobré je to třeba k tomu, že můžeš všechny ty auta naházet do jedné kolekce List<Auto> a pracovat s nima hromadně. Nebo třeba k tomu, že když důsledně dodržuješ programování oproti interface, tak můžeš později konkrétní implementaci snadno změnit. Dobrý příklad je třeba zrovna ten List. List je jenom rozhraní, nejspíš bys použil konkrétní implementaci ArrayList:

List<Auto> auta = new ArrayList<>();

ale když by ses později rozhodl, že pro tvé účely je lepší LinkedList, stačilo by ti to změnit pouze na

List<Auto> auta = new LinkedList<>();

a ve zbytku aplikace bys nemusel měnit vůbec nic.

 
Odpovědět
24.6.2023 13:23
Avatar
Lukáš Raška:25.7.2023 21:28

Zatím mi není moc jasné, k čemu je to vlastně dobré. Metody mohu volat na třídě i na rozhraní Co získám tím, že třídě omezím volání metod pomocí interface?
Uvítal bych, kdyby tu bylo více rozepsané praktické využití.. ale snad se to dozvím dále...

 
Odpovědět
+2
25.7.2023 21:28
Avatar
Vojtěch
Člen
Avatar
Vojtěch:5.4.2024 9:37

Doporučuji se zde víc pobavit a vysvětlit co se rozumí pod pojem "Programovat proti rozhraní", pokud jsem to přehlédl opravte mě, nicméně mám pocit, že v kurzu tato problematika nebyla vysvětlena - přitom se tato znalost v navazujících dílech předpokládá... (Spring, Kolekce)....dost mě to zmátlo, respektive nutilo hledat jinde o co vlastně jde....zkušený programátor to bere jako samozřejmost.­...nicméně my začátečníci bohužel ne....Díky

 
Odpovědět
5.4.2024 9:37
Avatar
Jaromír Jurkovič:3.8.2024 12:51

Lekce je trochu zmatená a mohla by lépe vysvětlit praktický význam rozhraní.

 
Odpovědět
3.8.2024 12:51
Avatar
Lubomír Čipčala:28.12.2024 17:01

Takto jednoduše by mělo být vysvětleno vše, bohužel tomu tak v 70 % není, což je veliká škoda

 
Odpovědět
28.12.2024 17:01
Avatar
Vojtěch Kadlec:7. února 10:55

Všechny dodatečné materiály v komentech pomohli, ale nevím jsetli tam úplně jsem. Po brouzdání po netu jsem si to ucelil, takto. Prosím o potvrzení.

1. Smyslem rozhraní je oddělit vrstvu komunikující ven vůči vrstvě implementující metody.
viz Továrna na auta zde v komentech. Kde na vstupu neřeším, co mi bude vráceno.

2. rozhraní mi dává možnost pracovat s dědičností na abstraktní úrovni, tak kde nedává symsl instance nebo chci kombici dědičnosti:

public interface Zvire {
        delejZvuky();
        dychej();
        }

public interface Ptaci extends Zvire {
        letej();
        }

public interface Plazi extends Zvire {
        plazSe();
        }

public interface Dravci {
        lov();
        }

public interface Bilozravci {
        pasSe();
        }

public class Pevci implements Ptaci, Bilozravci {
        // musím implementovat všechny metody
        delejZvuky();
        dychej();
        letej();
        pasSe();

public class Sykorka extends Pevci {
        //rozšiřuje vlastní atributy a metody
        }

public class PtakoJester implemets Ptaci, Plazi, Dravci {
        //zase implementuju metody

Za prvé neřešíme to přes třídy, protože dělat obecnou instatnci zvire nedáva logicky smysl.

Na druhou stranu jsem třídám dal hierarchii a ulehčil případné úpravy v budoucnu. Když doplním novou metodu do interface IDE mě vynadá, kde je potřeba implementovat.

A hlavně jsem s instancemi schopen pracovat na úrovni interface:

List<Zvire> zoo = new ArrayList<>;
zoo.add(konadra = new Sykorka() );
zoo.add(prisera = new Ptakojeste() );
System.out.println(zoo.size() );
for (Zvire zvire : zoo) {
        zvire.dychej();
        }
 
Odpovědět
7. února 10:55
Avatar
Vojtěch Kadlec:7. února 11:07

pomohli komentáře a další studium na webu, bez toho sem pochopil jak interface napsat, ale ne proč to udělat

 
Odpovědět
7. února 11:07
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 10 zpráv z 42.