Diskuze: Interface v Javě
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 10 zpráv z 10.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí Java, jsme si ověřili nabyté zkušenosti z kurzu.
Ahoj, rozhraní přesně jak říkáš pouze předepisuje, jaké metody musíš implementovat.
Vtip je v tom, že někdy potřebuješ dvě různé implementace jedné a té samé funkcionality. Pak vytvoříš dvě třídy, které budou implementovat jedno rozhraní, ale s rozdílnou implementací.
Pominu to, jak s rozhraním pracují frameworky (ty ho využívají v rámci
své logiky).
Takže úplně jasný příklad v praxi.
Dávám ti zadání:
Máš třídy:
Začnu třídami Dog, Bird a Cat (všechny budou velmi podobné)
Všechny tyto třídy budou mít jednu metodu - String
voice()
Tato metoda bude vracet zvuk toho zvířete.
No a metoda Main bude:
Takže pojďme na ty první tři třídy, ty budou vypadat následovně:
public class Dog {
public String voice() {
return "Hafiky haf";
}
}
public class Cat {
public String voice() {
return "mňau vole au";
}
}
public class Bird {
public String voice() {
return "kuku";
}
}
pardon, su vůl a dal jsem místo náhledu odeslat...
Tak a třída main bude (bez použití rozhraní) vypadat následovně:
public class Main {
public static void output(Dog dog) {
System.out.println(dog.voice());
}
public static void output(Cat cat) {
System.out.println(cat.voice());
}
public static void output(Bird bird) {
System.out.println(bird.voice());
}
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
Bird bird = new Bird();
output(dog);
output(cat);
output(bird);
}
}
No, takže máš 3 stejné metody, kterým ovšem předáváš různé
parametry, které ale dokonce provolávají stejnou metodu.
Což jaksi není moc efektivní. Teď si představ, že budeš mít takových
zvířat dvacet. To budeš pro každého zvířete speciálně definovat novou
metodu? (pakliže jo, tak příjemnou zábavu)
Já udělám radši tohle. Definuji nové rozhraní (Animal), které bude
předepisovat metodu String voice(). Tuto metodu budou všechny zvířata
implementovat.
Díky tomu mi stačí upravit kód v metodě main a místo x stejných metod s
různým parametrem bdudu předávat pouze jeden parametr a to společné
rozhraní (protože tím všechny ty třídy zjednotím). Takže kód bude
vypadat následovně:
public class Dog implements Animal {
@Override
public String voice() {
return "Hafiky haf";
}
}
public class Cat implements Animal {
@Override
public String voice() {
return "mňau vole au";
}
}
public class Bird implements Animal {
@Override
public String voice() {
return "kuku";
}
}
public interface Animal {
String voice();
}
public class Main {
public static void output(Animal animal) {
System.out.println(animal.voice());
}
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
Animal bird = new Bird();
output(dog);
output(cat);
output(bird);
}
}
Dále by následovala ukázka výhody abstraktní třídy, ovšem podstatnou výhodu abstrakce sebrala v Javě 7 defaultní metoda, ale na to ses už neptal:)
Jinak má rozhraní v praxi i úlohu takového spojovníka. V podstatě jako kdybys v kódu určoval (předepisoval), do které skupiny bude která class patřit (někdy je to dobré mít něco takového určeného a nezáleží na tom, v jakém balíčku taková třída bude). V podstatě z podobné logiky vychází i různé frameworky, například právě nejvíc populární Spring. DAOčka jsou rozhraní, které je nutno implementovat, ale představují služby, které máš v daném frameworku k dispozici. To, jak si je potom definuješ, to už je na tobě, ale navenek nabídneš pouze rozhraní.
Výše uvedený příklad je takovou typickou ukázkou použití rozhraní. Prostě abys nemusel vytvářet více metod pro stejný případ.
Kolega přede mnou to shrnul pěkně. Ještě bych ale doplnil, že rozhraní má ještě jednu a to ryze praktickou výhodu - dáváš do nich popis metod. I kdyby tak rozhraní implementovala pouze jedna jediná třída, tak ji velice zpřehledníš tím, že místo několik řádků dlouhých popisů každé metody, bude mít většina metod popis přímo v té třídě interface, a v samotné třídě, kde metodu implementuješ, bude pouze @Override.
Dále není příliš neobvyklé (ale ani přikázané), že máš-li tu
skupinu tříd, která implementuje jedno rozhraní, tak se snaž nepřidávat
do každé třídy další a další veřejné funkce. Spíše se snaž držet
jen těch funkcí, co jsou v rozhraní + pomocné privátní funkce, které
potřebuješ ke zjednodušení jejich implementace.
Když si vypůjčím příklad se zvířaty tak mohou být metody například
zmíněná voice (to ale není moc dobrý příklad, protože argument voice by
měl být argumentem třídy a tím pádem ti postačí jednoduchý getter).
Představ si například (nějakou složitější) metodu, která při
zavolání zjistí, kdy zvíře naposled jedlo, potom zjistí, jak často by
mělo jíst a případně jej nakrmí (pokud je to nutné). Rozdělíš to do
více funkcí, ale z pohledu uživatele (nebo hráče, protože tohle zní
spíše jako hra, že?) tě bude zajímat jen ta jedna jediná, v rámci které,
se provedou všechny ostatní. A tak ta jedna jediná bude funkce z interface,
budou ji mít všechna zvířata a ty ostatní nikdy nebudeš volat samostatně,
nebudeš je smět volat samostatně a hráč/uživatel vlastně ani nebude
vědět, že takové funkce existují. Podobně funkce například, kdy bylo
zvíře naposled na vycházce.
Vypadat to může nějak takhle
public interface Animal {
/**
*
* zjisti, kdy bylo zvire nakrmeno naposled a pripadne jej nakrmi
*
* @return true kdyz zvire bylo nakrmeno, jinak false
*/
boolean eating();
}
public class Dog implements Animal {
int lastMealInDays;
.... other arguments...
/**
*
* konstruktor
*/
public Dog(arguments...) {}
@Override
public boolean eating() {
implementation...
}
/**
*
*
* @return true kdyz zvire bylo nakrmeno, false pokud neni dost zradla
*/
private boolean feedDog() {
}
}
Chlapi, děkuji za podnětné rady. I když frameworks jsou ještě daleko
přede mnou
Ale pokud se to učíš takhle hezky od základu a máš takovéto dotazy
(mě se tedy tvůj dotaz líbil:) ), tak jsi na nejlepší cestě, aby ses to
naučil.
Vydrž, udržuj ten zájem a všechno to přijde samo. Nakonec poznáš, že
programování je sranda a budeš mít obrovskou moc v hlavě:)
(jen ti lidé, co ti budou zadávat úkoly budou mimo:D)
Jsem rád, že jste mně pomohli objasnit základy interfejsů v Javě.
Doporučil jsem tyto stránky známému, ale ten se hrabe v PHP.
Nechci tu moc obtěžovat, ale vzhledem k tématu jsem narazil ještě na
problém "značkovací interface - marker interface". Už je to trochu vousatý,
ale jeho znalost mě láká. Nemohl by sem někdo dát vysvětlení jako
Lubor?
Marker interface je prazdny interface, kterym oznacis tridu. Potom se pomoci operatoru instanceof muzes dotazat jestli je instance se kterou pracujes oznacena timto interfacem a na zaklade toho udelas nejake rozhodnuti.
Napriklad existuje Serializable interface, ktery rika, ze tridu je mozne serializovat. Samozrejme o serializaci se muzes pokusit u libovolne instance jakekoliv tridy ale ne u kazde to pujde. Kdyz nekdo oznaci tridu timto interfacem tak tim deklaruje, ze je mozne ji bez problemu (de)serializovat.
Zobrazeno 10 zpráv z 10.