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

Natix

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #15 kdy: 15. 07. 2013, 23:29:49 »
Ú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.

Třešnička na třešničce: V Javě 8 budou moci interfacy obsahovat i implementace instančních (a dokonce i statických) metod. Čili v název "interface" už nebude moc přesný, v podstatě půjde o mixiny. Ale i to je pořád nic proti scalovským traitům, což jsou v podstatě plnohodnotné abstraktní třídy, akorát bez konstruktoru.


Wilhelm

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #16 kdy: 15. 07. 2013, 23:43:40 »
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?

Kód: [Vybrat]
interface Foo
{
    void f();
}

interface Bar
{
    void f();
}

class MyClass1 : Foo, Bar
{
  public void f() { Console.WriteLine('A'); } //Implicitna implementacia
  void Foo.f() { Console.WriteLine('B'); } //Explicitna implementacia
  void Bar.f() { Console.WriteLine('C'); } //Explicitna implementacia
}

var obj = new MyClass();
obj.f(); //Vypise A
(obj as Foo).f(); //Vypise B
(obj as Bar).f(); //Vypise C

Natix

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #17 kdy: 16. 07. 2013, 00:18:30 »
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?

Kód: [Vybrat]
interface Foo
{
    void f();
}

interface Bar
{
    void f();
}

class MyClass1 : Foo, Bar
{
  public void f() { Console.WriteLine('A'); } //Implicitna implementacia
  void Foo.f() { Console.WriteLine('B'); } //Explicitna implementacia
  void Bar.f() { Console.WriteLine('C'); } //Explicitna implementacia
}

var obj = new MyClass();
obj.f(); //Vypise A
(obj as Foo).f(); //Vypise B
(obj as Bar).f(); //Vypise C

Aha, no tohle platí možná v C# nebo C++, ale pokud zůstaneme v kontextu Javy dle autora tématu, tak tam nic podobného neexistuje. Všechny metody v Javě jsou vždycky virtuální, takže se vždy volá implementace podle skutečné třídy daného objektu bez ohledu na typ reference, na které je metoda volaná.

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #18 kdy: 16. 07. 2013, 05:53:24 »
Není to úplně přesné - abstraktní třída může ale nemusí obsahovat kód.
A existuje nějaký rozumný důvod použít čistě abstraktní třídu bez proměnných, když můžu použít interfejs?  (pod "kód" jsem nešikovně zahrnul i data - proměnné).

Duro

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #19 kdy: 16. 07. 2013, 06:08:55 »
Triedna (aj abstraktna) je vztah typu is a(je). Rozhranie znamena can do (vie robit).

Napr. netopier je cicavec, holub je vtak, pterodaktyl je plaz. Toto je typicke zaradenie do tried a povedzme, ze triedna hierarchia kopiruje klasifikaciu zo zoologie. Pridajme k tomu lietadlo. Lietadlo je stroj. Co maju spolocne? Vedia robit podobny typ operacii - vzlietni, pristan, atd. Vztah, ktory definuje, co ma spolocne holub, pterodaktyl a lietadlo je typ vztahu can do (vie lietat), t.j. maju spolocne "rozhranie" pre lietajuce objekty.

Nez sa rozhodnem, ci je nieco trieda alebo rozhranie, polozim si presne tuto otazku, aky typ vztahu to reprezentuje. Ak by som si tuto otazku nepolozil, lahko dospejem k zlemu navrhu, kde holub aj lietadlo priamociaro dedia od nejakeho spolocneho predka - triedy. Dosledkom bude, ze sa stratim pri rozsirovani programu, ked sa budem stale budem borit s problemom, ze tie 2 veci vlastne nemaju nic spolocne, len v nejakej casti programu potrebujem vediet, ze oboje vedia lietat a vykonat s nimi nejaku "lietajucu" operaciu.


Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #20 kdy: 16. 07. 2013, 06:32:29 »
Nez sa rozhodnem, ci je nieco trieda alebo rozhranie, polozim si presne tuto otazku, aky typ vztahu to reprezentuje. Ak by som si tuto otazku nepolozil, lahko dospejem k zlemu navrhu, kde holub aj lietadlo priamociaro dedia od nejakeho spolocneho predka - triedy. Dosledkom bude, ze sa stratim pri rozsirovani programu, ked sa budem stale budem borit s problemom, ze tie 2 veci vlastne nemaju nic spolocne, len v nejakej casti programu potrebujem vediet, ze oboje vedia lietat a vykonat s nimi nejaku "lietajucu" operaciu.
To je sice hezká teorie, ale imho je to přesná ukázka přecenění OOP - představy, že "osekané" OOP je způsob myšlení, ktrerý je "přirozeným" základem jakýchkoli vztahů, abstrakcí.

Především to takhle těžko můžeš říct u jazyků, které nemají vícenásobnou dědičnost, protože jeden objekt samozřejmě může spadat do víc tříd, protože třída není nic jiného než abstraktní pojem, kterým pojmenováváme konkrétní objekty, které mají nějaké konkrétní vlastnosti. Neexistuje nic jako "přirozená kmenová třída",  což by byla abstraktní skupina, do které objekt patří "primárně" a která by tak byla jediným "správným" předkem všech objektů libovolné třídy X.

Např. ropa je (is-a) stejně tak "mazlavá tekutina" jako "palivo" a "organická sloučenina". Jazyk bez vícenásobné dědičnosti mě donutí k tomu, že budu tvrdit, že ropa je (is-a) primárně "organická sloučenina" plus má vlastnosti (can-do) paliva a mazlavé tekutiny, což zjevně neodpovídá skutečnosti, protože to můžu klidně udělat opačně (is-a palivo, can-do mazlavá).

Tomu, jak normálně pojmy používáme, by bylo imho daleko bližší používat interfejsy (klidně uspořádané do hierarchie, když už to teda chceme) plus mixiny, které ty interfejsy implementují, protože když už nějak formalizovat naše vnímání/myšlení, tak tak, že máme nějaké objekty, které mají nějaké (víceméně volně kombinovatelné) vlastnosti. Bohužel běžný programátor používá dědění na úkor skládání, což je imho opět neblahý vliv C++, ze kterého se ani Java pořádně nevymanila.

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #21 kdy: 16. 07. 2013, 06:51:44 »
A ještě dodatek: když se nad tím člověk zamyslí, může dojít k názoru, že vlastně vůbec nejlepší je se na celý OOP vykašlat a použít starý dobrý funkcionální přístup - objekt mám popsaný nějakou datovou strukturou plus k tomu mám nějaké funkce, které implementují vlastnosti a umí operovat nad datovými strukturami, které mají nějaké dané vlastnosti. A voilá, mám třídy interfejsů i mixiny, akorát tomu tak neříkám a musím si to trochu pohlídat sám, protože to není tak explicitní jako u OOP.

Duro

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #22 kdy: 16. 07. 2013, 06:54:48 »
To je sice pravda, ze nic ako "univerzalne platna" klasifikacia neexistuje ale na druhej strane, toto nie je specificky problem pre programovanie ale problem, ktory musi riesit kazdy, kto sa snazi zaradit veci do nejakych kategorii. Ak sa bavime o "prirodzenosti" takejto kategorizacie, tak "prirodzenost" nejde nad ramec pragmatickeho pristupu - staci, ak to je vseobecne zrozumitelne a co najpresnejsie odraza spolocne vlastnosti. Mne viacnasobna dedicnost nikdy nechybala, to je minor problem a separatna tema.  Ci je lepsie funkcionalne programovanie alebo oop je tiez separatna tema, bavime sa o tom, co je v oop trieda a rozhranie.

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #23 kdy: 16. 07. 2013, 07:43:49 »
bavime sa o tom, co je v oop trieda a rozhranie.
Jasně, ale tak, jak jsi to napsal (vztahy se dělí na is-a a can-do) to prostě neodpovídá běžnému vnímání v případě, že vztahy is-a mám uspořádané do stromu, kde každý uzel může mít jenom *jednoho* rodiče. Tenhle způsob uvažování vede k tomu, že některé vztahy typu is-a *prohlásím* (uměle,libovolně) za can-do, protože nemůžu jinak. K čemu pak to rozdělení je?

Když už bych to takhle chtěl napsat, řekl bych, že konkrétní jazyk (např. Java) mi umožňuje jenom jednu vazbu is-a ke konkrétnímu rodiči. Nemůžu to ale postavit tak, že v rámci analýzy musím odlišit vztah is-a a can-do a podle toho to pak implementovat. Takhle to není a být nemůže.

Duro

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #24 kdy: 16. 07. 2013, 08:28:03 »
bavime sa o tom, co je v oop trieda a rozhranie.
Jasně, ale tak, jak jsi to napsal (vztahy se dělí na is-a a can-do) to prostě neodpovídá běžnému vnímání v případě, že vztahy is-a mám uspořádané do stromu, kde každý uzel může mít jenom *jednoho* rodiče. Tenhle způsob uvažování vede k tomu, že některé vztahy typu is-a *prohlásím* (uměle,libovolně) za can-do, protože nemůžu jinak. K čemu pak to rozdělení je?

Když už bych to takhle chtěl napsat, řekl bych, že konkrétní jazyk (např. Java) mi umožňuje jenom jednu vazbu is-a ke konkrétnímu rodiči. Nemůžu to ale postavit tak, že v rámci analýzy musím odlišit vztah is-a a can-do a podle toho to pak implementovat. Takhle to není a být nemůže.
Tato diskusia je mimo, lebo ty nenamietas ci je popis vztahu medzi triedou a rozhranim vo filozofii OOP spravne popisany (a tu nejde o Javu ale vesobecne o OOP), ale ci je to spravna metoda. Ano, v zmysle OOP je musis rozhodnut o typu vztahu presne ako pisem. Ci mozes mat jedneho alebo viac triednych predkov je zalezitost jazyka. Rozdiel medzi rozhranim a triedou je principialny - je to rozdiel v koncepte a v uceli.

Ani v pripade tiredneho dedenia od vylucne jedneho predka nie je navrh hierarchie o nic umelejsi ako inde, kde taku stromovu hierarchiu definujes (zoologia, botanika, atd).

Marek Mizera

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #25 kdy: 16. 07. 2013, 08:54:02 »
Nuz, toto su zakladne stavebne prvky OOP a tvojim cielom by malo byt naucit sa robit spravnu hierarchiu objektov.
To zaberie roky :)
Najprv treba zvladnut spravnu implementaciu troch zakladnych prvkov OOP, tj. spravne pouzivat zapuzdrenie, dedicnost a polymorfizmus.
Tu odporucam prejst viacero kapitol z knizky Effective Java (http://www.amazon.com/Effective-Java-Edition-Joshua-Bloch/dp/0321356683). Samozrejme cela kniha stoji za to, spada do kategorie 'must have' pre kazdeho javistu, myslim ze aj Gosling ju cital xD

Potom sa vrhnut na studium tzv. 'design patterns' (navrhove vzory).

Hlavne spravne pouzivanie design patterns a dobry odhad, kedy kde aky pattern implementovat je casto tazke rozhodnut, chce to skusenosti.

O navrhovych vzoroch su popisane kvanta clankov, staci sa spytat google, napr.: http://www.tutorialspoint.com/design_pattern/


Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #26 kdy: 16. 07. 2013, 09:28:19 »
Ani v pripade tiredneho dedenia od vylucne jedneho predka nie je navrh hierarchie o nic umelejsi ako inde, kde taku stromovu hierarchiu definujes (zoologia, botanika, atd).
Ano. Ale každý biolog si bude vědom, že to je jenom jeden z možných pohledů na realitu. Nebude tvrdit, že věci tak jsou, ale jenom, ře on si je tak roztřídil.

Rozdiel medzi rozhranim a triedou je principialny - je to rozdiel v koncepte a v uceli.
Naposledy se to pokusím ozřejmit: řekl jsi "Nez sa rozhodnem, ci je nieco trieda alebo rozhranie, polozim si presne tuto otazku, aky typ vztahu to reprezentuje."

Nepoložíš si otázku "jaký typ vztahu tam je" (v realitě), ale rozhodneš se, jaký typ vztahu tam uděláš.

Prostě tvrdím, že vztahy nemůžeš analyzovat přirozeně, nezávisle na jazyku a potom je implementovat, ale už u analýzy musíš myslet na to, co ti jazyk (v tomhle ohledu) umožňuje. A to je prostě špatně. A dvakrát špatně to je, pokud začneš tvrdit, že ty vztahy, které sis tam (kvůli omezení jazyka) dal, jsou tam i v realitě. Nejsou.

Howgh.

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #27 kdy: 16. 07. 2013, 09:49:29 »
 :o
Pěkně tomu nešťastníkovi pomáháte.

(příjdu, až tu bude deset stránek, snad už bude jasné, kdo ho má většího)

Duro

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #28 kdy: 16. 07. 2013, 10:27:35 »
Ani v pripade tiredneho dedenia od vylucne jedneho predka nie je navrh hierarchie o nic umelejsi ako inde, kde taku stromovu hierarchiu definujes (zoologia, botanika, atd).
Ano. Ale každý biolog si bude vědom, že to je jenom jeden z možných pohledů na realitu. Nebude tvrdit, že věci tak jsou, ale jenom, ře on si je tak roztřídil.

Rozdiel medzi rozhranim a triedou je principialny - je to rozdiel v koncepte a v uceli.
Naposledy se to pokusím ozřejmit: řekl jsi "Nez sa rozhodnem, ci je nieco trieda alebo rozhranie, polozim si presne tuto otazku, aky typ vztahu to reprezentuje."

Nepoložíš si otázku "jaký typ vztahu tam je" (v realitě), ale rozhodneš se, jaký typ vztahu tam uděláš.

Prostě tvrdím, že vztahy nemůžeš analyzovat přirozeně, nezávisle na jazyku a potom je implementovat, ale už u analýzy musíš myslet na to, co ti jazyk (v tomhle ohledu) umožňuje. A to je prostě špatně. A dvakrát špatně to je, pokud začneš tvrdit, že ty vztahy, které sis tam (kvůli omezení jazyka) dal, jsou tam i v realitě. Nejsou.

Howgh.
Nie, ja si polozim otazku presne tak ako som ju naformuloval:-) Snad ma nechces presvedcit, ze to robim inak. To, ze tebe takto polozena otazka nedava postacujucu odpoved, moze byt vec cviku. Je to dobra otazka a vedie ma k dobrym odpovediam. Ked sa chces zlepsit v navrhu, tiez si ju klad.

Ano, suhlasim, ze model nie je realita. A?

Lukas

Re:Java - rozhraní, dědičnost a abstraktní třídy
« Odpověď #29 kdy: 16. 07. 2013, 14:09:11 »
:o
Pěkně tomu nešťastníkovi pomáháte.

(příjdu, až tu bude deset stránek, snad už bude jasné, kdo ho má většího)
+1... Taky jsem chtěl ještě upřesnit svojí odpověď když jsem to teď viděl při plném vědomí, ale když jsem viděl co tu je za diskusi, tak to asi nemá cenu.