Mehrfachvererbung



  • Nur weil die beiden es so machen ist es deswegen nicht gut. Warum haben die Entwickler bei Microsoft(C#) und Sun(Java) die Mehrfachvererbung weggelassen? Warum hat eine rein oo Sprache wie Smalltalk keine Mehrfachvererbung?

    Wie Marcus schon sagte: Mehrfachvererbung in eine Sprache zu implementieren ist mit viel Aufwand (auch Kosten in der Wirtschaft genannt) verbunden. Ein Feature als Bug zu bezeichnen, kann nur jemand sagen, der davon nicht profitieren kann.

    Eine Gegenfrage: warum gibt es so nette Sprachen wie CaesarJ die genau dieses Defizit von Java kompensieren wollen? http://www.caesarj.org/ Komisch das es von der TU Darmstadt und den dort arbeitenden Profs entwickelt wird und auch noch von SIEMENS gesponsert wird, damit man endlich auf der Java-Platform unter anderem Mehrfachvererbung bekommt.

    Der Grund: Mehrfachvererbung widerspricht dem Vererbungsprinzip "ist ein"!

    Also wenn ich einen Dackel mit einem Terrier kreuze, dann ist der kleine Welpe der daraus kommt, kein Dackel-Terrier-Mischling? Was ist er dann? Nur ein Dackel? Oder nur ein Terrier? 😕 Das Beispiel mit dem "Amphibienfahrzeug" ist auch ein gutes Beispiel. Es ist ein Boot und ein Auto. Widerleg DAS mal!



  • Ich habe es nicht als Bug bezeichnet sondern lediglich gesagt, dass es in der oo Welt auch Alternativen gibt! Die meisten Vorlesungen und Veröffentlichungen zu gutem und reinem oo Design bescheiben es so wie ich es tat. Man kann Probleme meistens auf verschiedene Weisen lösen und häufig ist keine der beiden Varianten unbedingt besser. Jedoch gibt es den Unterschied zwischen einem praktischen Design und einem gutem oo Design.

    Artchi schrieb:

    Der Grund: Mehrfachvererbung widerspricht dem Vererbungsprinzip "ist ein"!

    Also wenn ich einen Dackel mit einem Terrier kreuze, dann ist der kleine Welpe der daraus kommt, kein Dackel-Terrier-Mischling? Was ist er dann? Nur ein Dackel? Oder nur ein Terrier?

    Weiterhin ein Säugetier oder Hund, weil das andere nämlich Instanzen sind. 😉

    Artchi schrieb:

    Das Beispiel mit dem "Amphibienfahrzeug" ist auch ein gutes Beispiel. Es ist ein Boot und ein Auto. Widerleg DAS mal!

    Genau das ist ein Paradebeispiel für die Verwendung von Interfaces(nicht auf Java/C# bezogen). Wie wäre es mit AmphiFahrzeug erbt von Fahrzeug und implementiert das Interface Swimable?



  • das Beispiel mit dem Amphibienfahrzeug kann man verschieden lösen.
    Zum einen kann man eine neue Unterklasse Amphibienfahrzeuge definieren das von Fortbewegungsmittel erbt.
    Zum zweiten kann man das State-Pattern machen (oder war das das Delegation-Pattern?). Ist das Fahrzeug auf Wasser werden die Methoden von Boote aufgerufen, auf Land die Methoden von Fahrzeuge.

    Es gibt kein Beispiel das man nicht ohne Mehrfachvererbung lösen kann. Ob C++ oder Java beides ist Turing-Vollständig.

    Mehrfachvererbung ist IMHO etwas für Leute die gerne das und dies hätten aber nicht darüber nachdenken wollen wie es machen.

    Das Beispiel mit dem Dackel / Terrier ist nicht gültig. Du scheist Klassen und Attribute zu verwechseln. Beides sind Hunde. Ob es Dackel oder Terrier ist, entscheidet das Attribut Type. Oder willst du behaupten das ein Dackel etwas nicht kann was ein Terrier kann (oder umgekehrt) ?



  • DEvent schrieb:

    Das Beispiel mit dem Dackel / Terrier ist nicht gültig. Du scheist Klassen und Attribute zu verwechseln. Beides sind Hunde. Ob es Dackel oder Terrier ist, entscheidet das Attribut Type. Oder willst du behaupten das ein Dackel etwas nicht kann was ein Terrier kann (oder umgekehrt) ?

    Mein "Kleiner Münsterländer" ist ein Jagdhund, kann aber keine Schafe hüten. Oder willst du etwa behaupten, der einzige Unterschied von Hunden wäre ihr Aussehen? 😉



  • Pinguine sind auch Vögel, können die deswegen fliegen? Also, dann leite ich von Vogel ab, und implementiere die fliegen-Methode beim Pinguin leer. Also doch unterschiedliche Klassen. Ein Terrier grabt gerne Erde um (Terrier kommt von Tera), und ein Dackel jagt gerne, gräbt aber nicht gerade gerne Löscher in die Erde. Völlig zwei verschiede Verhaltensweisen. Wenn die jetzt nur unterschiedliche Fellfarbe usw. hätten, hätte ich das verstanden.

    AmphibienFzg implements Swimable? Eh, und wo sind die Attribite für das Ruder und die Schrauben die das Fzg im Wasser vorantreiben? Schön und gut das meine Fzg ein Swimable-Methode hat. Aber von Ufer A nach Ufer B werde ich ohne Eigenschaften von einem Boot nicht weit kommen. Also brauche ich doch eine Klasse mit Eigenschaften und Methoden eines Bootes.

    Umgekehrt genauso: Boot implements Driveable? Ohne vier Räder wirds auch schwierig damit zum Supermarkt zu fahren.

    Leute, denkt doch mal nach... :p



  • DEvent schrieb:

    Das Beispiel mit dem Dackel / Terrier ist nicht gültig. Du scheist Klassen und Attribute zu verwechseln. Beides sind Hunde. Ob es Dackel oder Terrier ist, entscheidet das Attribut Type.

    Also soll ich irgendwo eine switch-case-Anweisung haben um den Typ rauszufinden?



  • Stimmt! Dieses problem lässt sich ohne Mehrfachvererbung nicht lösen. 🙄

    Für mich ist hier EOD!

    BTW: Hast Du Dir mal das oben von mir genannte Delegation-Pattern angeschaut?



  • Artchi schrieb:

    DEvent schrieb:

    Das Beispiel mit dem Dackel / Terrier ist nicht gültig. Du scheist Klassen und Attribute zu verwechseln. Beides sind Hunde. Ob es Dackel oder Terrier ist, entscheidet das Attribut Type.

    Also soll ich irgendwo eine switch-case-Anweisung haben um den Typ rauszufinden?

    Nein, du hast einfach eine Stateklasse, die das dann über virtuelle Methoden
    regelt, dann rufst du Hund::GetState auf, um den aktuellen Status zu bekommen.
    Um zu wissen was für einen Hund du hast, musst du dann Hund::GetState()->toString()
    aufrufen, alternativ kannst du auch Hund::GetCurrentStateType aufrufen, per RTTI
    kannst du dann auf den zurückgegeben Typen abfragen.



  • Artchi schrieb:

    Pinguine sind auch Vögel, können die deswegen fliegen? Also, dann leite ich von Vogel ab, und implementiere die fliegen-Methode beim Pinguin leer.

    Nee, Fliegen hat in ner abstrakten Klasse Vogel noch gar nix zu suchen, denn es gibt genug Vögel, die dies nicht können.

    Ein Terrier grabt gerne Erde um (Terrier kommt von Tera), und ein Dackel jagt gerne, gräbt aber nicht gerade gerne Löscher in die Erde. Völlig zwei verschiede Verhaltensweisen.

    Und dann willst du, dass der Mischling von Terrier und von Dackel ableitet? Dann könnte ich mir ja den Superhund züchten, der aus allen Arten gemischt wird.

    IMHO sollte der Mischling genauso wie die reinrassigen Hunde von AbstractHund ableiten. So kann man genau festlegen, was der Hund wirklich kann und muss nicht irgendwelche Methoden leer definieren.



  • Nochmal zum Thema Ampfibienfahrzeug:

    Kann man hier nicht einfach eine eigene Klasse erstellen die weder von Boot noch von Fahrzeug erbt und diese beiden einfach inkludieren? So könnte man deren Funktionen je nach Bedarf nutzen... z.B. BewegeVonAnachB(...) würde im Wasser einfach Boot::Schwimme und an Land Fahrzeug::Fahre aufrufen.



  • Chris++ schrieb:

    Nochmal zum Thema Ampfibienfahrzeug:

    Kann man hier nicht einfach eine eigene Klasse erstellen die weder von Boot noch von Fahrzeug erbt und diese beiden einfach inkludieren? So könnte man deren Funktionen je nach Bedarf nutzen... z.B. BewegeVonAnachB(...) würde im Wasser einfach Boot::Schwimme und an Land Fahrzeug::Fahre aufrufen.

    Das ist ja genau das State-Pattern. Je nach State schwimmt oder fährt das Object von A nach B. Wie es das tut interessiert den Benutzer nicht im geringsten, solange es in B ankommt.



  • Hallo, realisiert vielleicht mal, dass man ohne Kontext überhaupt nicht sinnvoll entscheiden kann, ob es jetzt geil ist, dies von jenes abzuleiten.

    In meine Auto-Klasse tu ich auch nicht ein Attribut Lackfarbe rein, wenn ich das nachher im Programm nicht brauche, mit der Begründung "ein Auto HAT doch eine Lackfarbe". Ich brauche in meinem Programm vielleicht auch nicht, dass eine Amsel ein Vogel ist sondern es reicht mir zu wissen, dass es fliegen kann. Also gibt es keine Vogel-Klasse. Auf blöd kann es aber auch völlig ok sein, dass alle Vögel fliegen können.

    Beim Modellieren geht es nicht darum, die Realität nachzubilden, sondern das was für das Programm notwendig ist, sauber in Konzepte aufzuteilen. Das ist übrigens auch der Grund, warum man so oft ohne Mehrfachvererbung auskommen kann, obwohl die Realität voll davon ist. Allgemeine Diskussionen und Aussagen wie "Ein Amphibienfahrzeug ist ein Landfahrzeug und ist ein Luftfahrzeug" oder "fliegen() gehört nicht in die Klasse Vogel" haben völlig ohne Kontext überhaupt keinen Wert.



  • Hallo:

    Na, hier ist ein Kontext: Es sollen Klassen erstellt werden für den
    Verkaufskatalog eines Fortbewegungsmittel-Herstellers. Zunächst gibt es eine
    Klasse "Fahrzeuge" mit den Unterklassen "Auto","LKW","Fahrrad", sodann eine
    Klasse "Boote" mit den Unterklassen "Ruderboot","Motorboot","Segelboot".

    Und nun baut der Hersteller ein Amphibienfahrzeug. Naheliegend (und sicherlich
    kein Design-Fehler!) wäre es, eine Klasse "Amphibienfahrzeug" abzuleiten
    von "Fahrzeug" und "Boot". Von "Fahrzeug" erbt es die Attribute "Anzahl Räder",
    "Reifengröße" etc. von "Boot" erbt es "Anzahl Schiffsschrauben". Beim "Preis"
    wird es schwierig, denn "Boot" und "Fahrzeug" haben beide einen, aber das ist
    eben eines der bekannten Probleme bei Mehfachvererbung.

    Wie man sieht, hat sich das Problem durch Darstellung des Kontexts aber weder
    aufgelöst noch substanziell verändert. In diesem Fall ist Mehrfachvererbung
    eben doch die nächstliegende Lösung.

    Ciao



  • Quodli Z. schrieb:

    Hallo:

    Na, hier ist ein Kontext: Es sollen Klassen erstellt werden für den
    Verkaufskatalog eines Fortbewegungsmittel-Herstellers. Zunächst gibt es eine
    Klasse "Fahrzeuge" mit den Unterklassen "Auto","LKW","Fahrrad", sodann eine
    Klasse "Boote" mit den Unterklassen "Ruderboot","Motorboot","Segelboot".

    Und nun baut der Hersteller ein Amphibienfahrzeug. Naheliegend (und sicherlich
    kein Design-Fehler!) wäre es, eine Klasse "Amphibienfahrzeug" abzuleiten
    von "Fahrzeug" und "Boot". Von "Fahrzeug" erbt es die Attribute "Anzahl Räder",
    "Reifengröße" etc. von "Boot" erbt es "Anzahl Schiffsschrauben". Beim "Preis"
    wird es schwierig, denn "Boot" und "Fahrzeug" haben beide einen, aber das ist
    eben eines der bekannten Probleme bei Mehfachvererbung.

    Wie man sieht, hat sich das Problem durch Darstellung des Kontexts aber weder
    aufgelöst noch substanziell verändert. In diesem Fall ist Mehrfachvererbung
    eben doch die nächstliegende Lösung.

    Ciao

    Ich bezweifle mal schwer, das wenn du ein Auto mit einem Boot kreuzt, das dann
    ein Amphibienfahrzeug rauskommt 🙄
    Genauso gut könnte man Batman von Mensch und Fledermaus ableiten, das ergäbe
    ungefähr genau so viel sinn...

    phlox



  • ...Mit anderen Worten: Im Beispiel "Amphibendahrzeug" <-- ("Boot","Fahrzeug")
    ist Mehrfachvererbung eben doch der nächstliegende Weg zur Klasseneinteilung
    und kein Design-Fehler.

    Ciao



  • Quodli Z. schrieb:

    ...Mit anderen Worten: Im Beispiel "Amphibendahrzeug" <-- ("Boot","Fahrzeug")
    ist Mehrfachvererbung eben doch der nächstliegende Weg zur Klasseneinteilung
    und kein Design-Fehler.

    Ciao

    Doch ist es. Weils es eben KEIN Boot ist, und auch KEIN Auto.
    Wenn du nun eine Klasse Amphibienfahrzeug von Fahrzeug ableitest,
    dann kannst du über ein Statepattern definieren was es gerade macht,
    und wie es das gerade macht. Mit Mehrfachvererbung kannst du das
    nicht, weil dann kannst du im Wasser die Methode Fahren für die Räder
    aufrufen, ist aber nicht sinnvoll...



  • Ja, wie im realen Leben kann ich vom AmphibienFzg die Räder drehen lassen (fahren()-Methode) und es passiert tatsächlich nichts außer das Wasser überall aufspritzt. Und? Realistischer kann das Klassenverhalten nicht sein.



  • @phlox81:
    Um Optimizers letzten Post nochmal aufzugreifen, muss die Klasse Amphibienfahrzeug, die für einen Katalog eines Fahrzeugherstellers designt wurde, schwimmen und fahren können?



  • In dem konkreten Beispiel nicht.



  • Artchi schrieb:

    Ja, wie im realen Leben kann ich vom AmphibienFzg die Räder drehen lassen (fahren()-Methode) und es passiert tatsächlich nichts außer das Wasser überall aufspritzt. Und? Realistischer kann das Klassenverhalten nicht sein.

    Ich als Benutzer würde es aber erwarte.
    Ich denke mir: Die Klasse hat die Methode fahren() also wird das Fahrzeug von A nach B bewegt. Woher soll ich den wissen das ich auf einmal nicht die Methode fahren() aufrufen muss, sondern die Methode schwimmen() ?


Anmelden zum Antworten