Diskuze: "MultiDědičnost" v Javě

Java Java "MultiDědičnost" v Javě

Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

Ahoj,

pochopitelně nejsem blb a vím, že multidědičnost v Javě je oximoron, ale potřeboval bych vědět, jak se dá takový případ řešit. Mám i konkrétní případ, který mě sice napadl, ale nevím si s ním rady:)
Mám 3 třídy. Matka, Otec a Syn. Matka obsahuje metodu uvarit() a Otec obsahuje metodu opravAuto(). Po třídě Syn chci, aby tyto obě metody zdědila. Jak to udělat? Jediné, co jsem se dočetl na netu, tak všichni pouze podotkli: "vícenásobná dědičnost v Javě se dělá přes rozhraní". Ale hlavně jsem se setkával s novodobým faktem, že Java může dědit pouze od jednoho předka, ale může implementovat jakýkoliv počet rozhraní, což je sice jasná a pravdivá definice, ale jaksi mi neodopovídá na mou otázku:D Poradí někdo?

Odpovědět 28. března 11:00
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Lukas C#
Redaktor
Avatar
Lukas C#:

Udělej si třeba 2 rozhraní: IMatka, IOtec, v Imatka bude Uvarit(), v IOtec opravAuto, no a Syn ať "zdědí" z obou těchto rozhraní. Samozřejmě třída Matka bude implementovat IMatka, a Otec IOtec.

 
Nahoru Odpovědět 28. března 12:03
Avatar
mayo505
Redaktor
Avatar
Odpovídá na Lubor Pešek
mayo505:

Podľa mňa je to zlý príklad dedičnosti. Najlepšie použitie dedičnosti je vo vzťahu generalizácia - špecializácia, resp. je tam vzťah "JE". Syn ale nie je špeciálny typ otca a ani neplatí, že syn JE otec (resp. nie vždy). Príklad môže byť osoba - syn ... syn je špeciálnym prípadom osoby a syn JE osoba.
Použitie dedičnosti iba aby sa zdedila nejaká funkcionalita je podľa mňa zlé z pohľadu návrhu.

 
Nahoru Odpovědět 28. března 12:18
Avatar
Atrament
Člen
Avatar
Atrament:

Matka, Otec a Syn jsou především speciální případy Osoby. Nějakým způsobem rozšiřují Osobu. Tento vztah mezi třídami se modeluje pomocí dědičnosti takže každá tato třída by měla dědit od Osoby:

public class Matka extends Osoba ...

Všechny tyto speciální případy mají dále nějakou speciální funkcionalitu, tento vztah se modeluje pomocí interface - chceš aby někdo uměl vařit a někdo opravovat auto, případně někdo aby uměl obojí. Takže potřebuješ interface pro Kuchaře a pro Opraváře. Funkcionalitu pak dodáš podle potřeby tomu komu chceš:

public class Matka extends Osoba implements Kuchař ...
public class Otec extends Osoba implements Opravář ...
public class Syn extends Osoba implements Kuchař, Opravář ...

Kuchař by mohl vypadat nějak takto:

public interface Kuchař {
  public void uvař();
}

Opravář:

public interface Opravář {
  public void oprav();
}
 
Nahoru Odpovědět  +2 28. března 12:31
Avatar
Lubor Pešek
Člen
Avatar
Lubor Pešek:

Dík za odpovědi, ale přes ten interface dochází přesně k onu případu, který jsem nechtěl - Matka i Otec musí mít obě metody. Je to pochopitelně jen cvičný příklad a kýženého výsledku by se dalo dojít normální cestou x možnostmi.

Mě šlo o to, když bych potřeboval ze dvou různých tříd, na sobě nezávislých, dědit a potřeboval bych od každé třeba 5 metod, ale pro jednoduchost jsem v příkladu uvedl jednu metodu od každého. Interface jsem přesně takhle použil, jak popisujete, ale (a to jsem zapoměl dodat, to se omlouvám) co když nemůžu zasahovat do "nadřazených" tříd a implementovat jim prázdné metody z rozhraní? (navíc potom by ani syn nevěděl, jestli dědit prázdnou metodu Otce nebo definovanou metodu Matky, muselo by se to zase konkretizovat.

Samozřejmě, že nejjednodušší cesta je udělat si dvě instance (Matky i Otce) ve třídě Syn a pak zavolat tyto metody a ano, není to geniální příklad dědičnosti. Je to vyjímečná situace a jde mi o ten princip.

Nahoru Odpovědět 28. března 14:23
Existují dva způsoby, jak vyřešit problém. Za prvé vyhoďte počítač z okna. Za druhé vyhoďte okna z počítače.
Avatar
Atrament
Člen
Avatar
Odpovídá na Lubor Pešek
Atrament:

Neměl bys chtít dědit ze dvou nezávislých tříd, to je logický nesmysl, pokud ty třídy spolu nemají nic společného, tak proč by měli mít nějakého společného potomka (odmyslíme-li si fakt, že to v Javě ani nejde). Pokud by ses snad do takové situace dostal, je to jasný indikátor, že je aplikace špatně navržená.

Dědičnost neslouží k tomu aby sis skládal třídy dohromady, tu pět funkcí z tohodle, tu deset funkcí z támhletoho... Dědičnost slouží k rozšíření funkcionality již existující třídy, která to umožňuje.

To co ty chceš je kompozice. Skládání několika funkcionalit dohromady pomocí interface, tak jak jsem to popsal výše.

přes ten interface dochází přesně k onu případu, který jsem nechtěl - Matka i Otec musí mít obě metody.

Tuhle poznámku jsem nepochopil, mohl bys to trochu rozvést? Jaké obě metody?

Já chápu, že rodinné vztahy Otec, Matka, Syn tak nějak svádějí k použití dědičnosti, ale je to v tomhle případě chyba, Syn není v tomto případě žádné rozšíření Otce a Matky, nic od nich nedědí, on akorát v sobě skládá část funkcionality Otce a část funkcionality Matky, takže se jedná o jasnou kompozici.

 
Nahoru Odpovědět  +1 28. března 14:51
Avatar
mayo505
Redaktor
Avatar
Odpovídá na Lubor Pešek
mayo505:

a ano, není to geniální příklad dědičnosti. Je to vyjímečná situace a jde mi o ten princip.

Ja som to myslel práve tak, že keď potrebuješ viacnásobnú dedičnosť tak niečo "smrdí" a je to lepšie nepoužiť. Je to znak toho, že dedíš iba preto lebo chceš zdediť a nahromadiť funkcionalitu z viacerých tried (tak to aj popisuješ), bez nejakého logického konceptu a to nie je dobrý typ dedičnosti.

http://www.javaworld.com/…is-evil.html

Editováno 28. března 15:04
 
Nahoru Odpovědět 28. března 15:02
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 7 zpráv z 7.