Java - rozhraní, dědičnost a abstraktní třídy

Martin

Java - rozhraní, dědičnost a abstraktní třídy
« kdy: 15. 07. 2013, 21:05:50 »
Ahoj, učím se programovat javě, a narazil jsem na pojmy rozhraní, dědičnost a abstratkní třídy. Když jsem si o nich vyhledal o každém něco zvlášť, myslím, že vím, co to asi tak je, ale nevím, co je kde vhodnější použít, na některých místech bych použil ono, nicméně všichni tam používají to druhé, jak tyto případy odlišit? Čeho se držet?
Předem díky za odpovědi a hezký večer.


DK

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #1 kdy: 15. 07. 2013, 21:16:53 »
to je jako se zeptat na rozdil mezi bramborem, nozem a vrtackou

rozhrani je ciste abstraktni trida, ktera definuje zakladni vlastnosti potomka
abstraktni trida je trida, ktera se musi dedit, protoze sama o sobe nemuze existovat
dedicnost je vlastnost vlastnictvi vlastnosti nadrazeneho objektu

nicmene zakladem je se naucit OOP, jakmile to neumite, neucte se javu

Martin

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #2 kdy: 15. 07. 2013, 21:35:16 »
Já jsem ani tak nemyslel co přesně to je, spíš jaký je v tomr rozdíl, a co kde použít, neboť se mi často stává, že bych někde použil klidně to i to a nevím co si pak vybrat.

ips

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #3 kdy: 15. 07. 2013, 21:45:27 »
Rozhraní je přesně to, co říká název. Je to něco jako předpis, jak s objektem komunikovat. Sdružuje prototypy metod a pokud jej třída implementuje, musí dodat také implementaci všem těmto metodám. Používá se pro třídy, které mají různý charakter, ale dá se s nimi principielně provádět několik stejných akcí. Tyto akce je pak lepší sdružit do rozhraní a naimplementovat.

Abstraktní třída slouží jako abstraktní základ hierarchie dědičnosti. Tady se snadno najde příklad z reálného života. Třeba třída Zvíře, od které budou dědit třídy jako Pes, Kočka atd... Zvíře bude sdružovat všechny společné vlastnosti všech zvířat (věk, hmotnost atd...) a metody všech zvířat, ale nedává smysl, aby vznikla instance Zvířete, ta prostě existovat nemůže. Všechno, co tedy bude zvíře obsahovat, se v konkrétních instancích bude vyskytovat pouze jako součást potomků v hierarchii.

Martin

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #4 kdy: 15. 07. 2013, 21:49:07 »
Aha, ale kde se vezme ta hranice toho, co může být instance a co ne? Vždyť přece Pes může být také abstraktní - dědí Zlatý retrívr a Kokršpaněl. Proč nepoužít tedy jen jedno? Nebo jsem v tom přehlédl nějaký zásadní rozdíl? Resp. u abstratkních tříd dje jen o to, aby se nedali vytvořit, ale jinak jsou v zásadě podobné dědičnosti?


ips

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #5 kdy: 15. 07. 2013, 22:05:05 »
Tak přirozeně, tohle je příklad ze života, při programování konkrétních projektů je ta hranice celkem jasná. Hezký praktický příklad je třeba ve hrách - ve strategii budeš mít různé jednotky. Pro ně si uděláš nějakou abstraktní třídu Unit, od které bude každý konkrétní typ jednotky dědit. Unit pak bude obsahovat pole pro HP jednotky (každá jednotka má HP), bude implementovat základní metody pro pohyb jednotky (každá jednotka se pohybuje stejně, jen např. různou rychlostí, tu ale bude mít každý potomek nastavenou zvlášť), bude typicky implementovat prázdnou abstraktní metodu pro útočení (každá jednotka umí útočit, ale většinou to každá dělá nějak jinak). Zde by se třeba hodilo si vytvořit ještě další patro v hierarchii složené z abstraktních tříd jako MeleeUnit, RangedUnit, atd... kde každá tahle abstraktní třída už bude implementovat metodu pro útok, protože všichni potomci útočí stejně, jen třeba různou silou, což si opět nastaví každý zvlášť. Doufám, že je to pochopitelné.

Wilhelm

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #6 kdy: 15. 07. 2013, 22:11:50 »
Vyhoda Abstraktnej triedy je v tom - ze v nej mozes ciastocne naimplementovat niektore casti triedy a nemusis to zakazdym implementovat v potomkovi. Nevyhoda je ze mozes dedit len jednu abstraktnu triedu.

Naopak ked dedis rozhranie musis kod kazdej metody v kazdom potomkovi vzdy nanovo naimplementovat. Vyhoda rozhrania je v tom ze kazda trieda moze dedit viac rozhrani a moze sa na ne pretypovat.

(Toto obmedzenie plati len pre jazyky s jednoduchou dedicnostou)

Lukas

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #7 kdy: 15. 07. 2013, 22:38:58 »
Ja bych to popsal trochu jinak, alespon z meho pohledu jak jsem se s tim setkal, a omlouvam se za styl, javu jsem uz nejaky patek nevidel.

Rozhrani je vetsinou udelane tak ze bud dava objektu nejakou vlastnost, nebo standartizuje nejaky set funkci (vcetne vstupnich parametru a navratovych hodnot) ktere objekt musi mit aby s nim slo neco delat. Interface nepopisuje objekt co do informaci ktere uklada ale co do metod ktere obsahuje.

Dal bych za priklad tridu cislo. Ta ma rozhrani comparable, cili to rika ze trida jde s necim srovnavat. Rozhrani comparable, tak jak je definovane nekde jinde, vyzaduje, aby trida mela nekde metodu int compareTo(object input). kde bude definovane ze vraci retval<0 kdyz je cislo mensi nez parametr predany jako argument, nulu kdyz je stejne a retval>0 kdyz bude argument mensi.

Treba.

Objekt nemusi byt cislo, predstav si ze mas objekt co ma v sobe obrazek a ty muzes udelat funkci compareTo co srovna zda je obrazek tmavsi nez jinej atd atd.

Priklad s cislem :
Kód: [Vybrat]
public class Cislo implements Comparable {

    double number;

    public Cislo () {
        numberl = 0.0;
    }

    public Cislo (double _number) {
        number= _number;
    }

    public String toString() {
        return number;
    }

    public int compareTo(Object o1)
    {
        if (this.number== ((Cislo) o1).number)
            return 0;
        else if ((this.number) > ((Cislo) o1).number)
            return 1;
        else
            return -1;
    }
}


Tehle vlastnosti muze byt hodne, napada me treba serializable, printable...
Pokud si dobre vzpominam tak v Jave muze objekt implementovat neomezene interfacu.

Abstraktni tridu si prestav jako sablonu. POZOR - abstraktni trida je tehdy, pokud v sobe ma alespon jednu abstraktni metodu. Me tohle ucili na obrazcich. Priklad >
Mas Abstrakni tridu Geometricky tvar.
Kód: [Vybrat]
Abstract class GeometrickyTvar
{
abstract  int numStran; // jen promenna

abstract int draw(); // nejaka metoda
}

// no a zde se dedi :
class Trojuhelnik extends Geometricky tvar
{
int a,b,c; // strany.
}

...
...
if (trojuhelnik.numStran != 3) return "chyba"; //no a v kodu muzes pak pouzit num stran prestoze v tom trojuhelniku nikde neni

Koukam ze abstraktni tridou jsem vzal i dedicnost, takhle se rika tomu ze jedna trida se zkopiruje do druhe a prida vlastni vlastnosti.

Dedit se v jave da jen z jedne tridy, nicmene jedna trida muze mit kolik chce rozhrani. ( teda myslim, to si radsi over )

Skoukni knihu/net, uz nemam sil... snad jsem alespon trochu pomohl, GN =)

Lukas

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #8 kdy: 15. 07. 2013, 22:43:03 »
Ach, koukam ze jsem omylem vymazal jednu dulezitou cast - abstrakni trida/metoda je takova ktera nema alespon jednu metodu z implementovanou, ma napsane jen jeji jmeno a IO parametry.

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #9 kdy: 15. 07. 2013, 22:43:29 »
Úplně polopaticky řečeno: abstraktní třída obsahuje nějaký kód, který potomci můžou zdědit, zatímco interface žádný kód neobsahuje - popisuje jenom, jaké metody má mít třída, která interface implementuje.

Proto taky ta terminologie: z abstraktní třídy se dědí, zatímco interface se implementuje.

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #10 kdy: 15. 07. 2013, 22:49:08 »
Rozhrani je vetsinou udelane tak ze bud dava objektu nejakou vlastnost, nebo standartizuje nejaky set funkci (vcetne vstupnich parametru a navratovych hodnot) ktere objekt musi mit aby s nim slo neco delat. Interface nepopisuje objekt co do informaci ktere uklada ale co do metod ktere obsahuje.
<flame mode on>Kdyby nebyli všichni pomatení z C++ a java by to názvosloví částečně nepřejala, bylo by to daleko jasnější:<flame mode off> interface definuje, jakým zprávám má objekt rozumět. V Objective C se tomu celkem přiléhavě říká "protokol" ( viz http://goo.gl/YTv48 )

mm

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #11 kdy: 15. 07. 2013, 22:50:49 »
Na abstraktní třídy a dědičnost se vyser. Napiš si v Javě pár prográmků a tyhle věci přijdou samy.

Wilhelm

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #12 kdy: 15. 07. 2013, 22:53:17 »
A este doplnim ze u rozhrania si mozes zvolit 2 typy implementacie abstraktnych clenov:

1. implicitne
2. explicitne

(rozdiel je v nutnosti implicitneho a explicitneho pretypovania)

U abstraktnych tried je to vzdy implicitne.

Natix

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #13 kdy: 15. 07. 2013, 23:07:13 »
A este doplnim ze u rozhrania si mozes zvolit 2 typy implementacie abstraktnych clenov:

1. implicitne
2. explicitne

(rozdiel je v nutnosti implicitneho a explicitneho pretypovania)

U abstraktnych tried je to vzdy implicitne.

Promiň, možná jsi jenom použil pro mě neobvyklou terminologii, ale vůbec jsem nepochopil, co jsi chtěl tímhle říct. Můžeš uvést nějaký příklad?

B

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #14 kdy: 15. 07. 2013, 23:14:57 »
Úplně polopaticky řečeno: abstraktní třída obsahuje nějaký kód, který potomci můžou zdědit, zatímco interface žádný kód neobsahuje - popisuje jenom, jaké metody má mít třída, která interface implementuje.

Proto taky ta terminologie: z abstraktní třídy se dědí, zatímco interface se implementuje.

Není to úplně přesné - abstraktní třída může ale nemusí obsahovat kód.

Zásadní poznatek: interface je extrémní případ abstraktní třídy v tom smyslu že interface neobsahuje žádný kód - všechny metody jsou povinně abstraktní. Můžete u nich uvést identifikátor abstract ale nemusíte - stejně tam je (implicitně).

Další zásadní poznatek: interface nemůže (na rozdíl od abstraktních tříd) obsahovat žádné instanční proměnné (fieldy), což umožňuje aby třídy implementovaly více než jedno interface - googlujte "diamond problem" abyste pochopili o co jde.

A ještě třešnička na závěr: interface mohou mezi sebou dědit.