Mehrfachvererbung
-
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() ?
-
Ein Amphibienfahrzeug dürfte in einem Katalog unter "Spezialfahrzeuge" zu finden sein.
-
class AmphibienFzg : public Auto, Boot { bool wasserModus; public: // Diese Methode würden Auto und Boot auch haben, wird hier einfach überschrieben void bewege(Ort a, Ort b) { if(isWasserModus()) schwimme(a, b); else fahre(a, b); } void setWasserModus(Modus m) { wasserModus = m; } };
Will man das ganze Automatisiert haben und nicht manuell den Modus setzen, könnte man natürlich eine Entscheidung danach fällen, auf welchem Untergrund sich this gerade befindet. Je nach dem was simuliert werden soll. Hat das AmphibienFzg eine automatische Erkennung (Sensor) müsste man es entsprechenden implementieren. Sind natürlich ein paar Klassen mehr für nötig, z.B. eine Klasse WasserSensor. Kommt auf die Anforderungen an. Aber Mehrfachvererbung birngt, wie in dem Beispiel, keine Probleme. Der Benutzer des AmphibienFzg kann ganz normal die Bewegenmethode aufrufen, die jedes Fortbewegungsnmittel hat. Ich als Implementierer des AmphibienFzg entscheide, wie sich das Ding letztendlich bewegt.
Das ganze könnte auch mit einem Flugzeug funktionieren. Das Flugzeug hätte dann eine bewege()-Methode und ob dieses ein Wasserflugzeug ist ist mir als Aufrufer dann auch egal.
-
Das Amphibienfahrzeug ist doch außerhalb eines konkreten Programms reichlich unspezifiziert.
Nehmt zum Beispiel ein GUI-API. Jeder weiß, was ein simpler Button ist und in welchem Kontext er benutzt werden kann. Das einzige, wo da die Vorstellungen noch auseinander gehen könnten ist, kann ein Button Bilder oder andere Steuerelemente enthalten?
Auf jeden Fall ist die Art, wie ein Button sonst verwendet, ziemlich klar. Vielleicht könnte man hier mal versuchen, ein gutes Beispiel zu finden, wo man Mehrfachvererbung nutzbringend einsetzen könnte. Oder kennt jemand ein gutes C++ GUI API mit Mehrfachvererbung?
-
Artchi schrieb:
// Diese Methode würden Auto und Boot auch haben, wird hier einfach überschrieben
Genau, und ich bin der Weihnachtsmann. Welche Methode willst du denn überschreiben? Oder doch lieber Auto::bewege() und Boot::bewege()?
Aber Mehrfachvererbung birngt, wie in dem Beispiel, keine Probleme.
Doch. Du hast alles, was Fortbewegungsmittel jeder Art gemeinsam haben, zweimal geerbt. Herzlichen Glückwunsch, darf ich dir den Diamond of Death persönlich überreichen? Oder willst du mir glauben machen, dass Auto und Boot nichts gemeinsam hätten? Auto und Boot haben schon mal sicher mehr abstrakte Gemeinsamkeiten (Kapazität, Gewicht, Preis, Spritverbrach, Geschwindigkeit, ...) als ein Amphibienfahrzeug mit Boot. Davon mal abgesehen, hat dir die Mehrfachvererbung hier auch keine Vorteile gebracht.
-
Optimizer schrieb:
Oder kennt jemand ein gutes C++ GUI API mit Mehrfachvererbung?
Das imho am Besten designte C++ GUI Framework benutzt jedenfalls keine: http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/widget_hierarchy.html
-
Optimizer schrieb:
Aber Mehrfachvererbung birngt, wie in dem Beispiel, keine Probleme.
Doch. Du hast alles, was Fortbewegungsmittel jeder Art gemeinsam haben, zweimal geerbt. Herzlichen Glückwunsch, darf ich dir den Diamond of Death persönlich überreichen? Oder willst du mir glauben machen, dass Auto und Boot nichts gemeinsam hätten? Auto und Boot haben schon mal sicher mehr abstrakte Gemeinsamkeiten (Kapazität, Gewicht, Preis, Spritverbrach, Geschwindigkeit, ...) als ein Amphibienfahrzeug mit Boot. Davon mal abgesehen, hat dir die Mehrfachvererbung hier auch keine Vorteile gebracht.
Geil geschrieben
Mich würde jetzt mal interessieren wie du das Problem lösen würdest. Also ich würde es weiterhin so wie in meinem vorhergehenden Beitrag machen.
-
Das Beispiel ist doch falsch.
Ein AmphibienFz steht doch hierarchisch auf der selben Ebene wie Auto und Boot, erbt also nur von Fahrzeuge gemeinsames.Ich würd den Stammbaum zB so zeichnen:
Fahrzeug ( Grösse, Gewicht, Bewegen() ) / | \ Landfahrzeug Hybrid/Mutlifnkt. Wasserfahrzeug / \ / \ / \ 2 Räder 4 Räd. Amphi. Hoovercr. Motorboot Segelboot
-
Optimizer schrieb:
Artchi schrieb:
// Diese Methode würden Auto und Boot auch haben, wird hier einfach überschrieben
Genau, und ich bin der Weihnachtsmann. Welche Methode willst du denn überschreiben? Oder doch lieber Auto::bewege() und Boot::bewege()?
Auto und Boot sind virtuell abgeleitete Klassen, und du hast die Doppeldeutigkeit aufgelöst.
Beispiel:
class Auto : virtual public AutoBase { void fahre(Ort a, Ort b) { AutoBase::bewege(a, b); } }; class Boot : virtual public BootBase { void schwimme(Ort a, Ort b) { BootBase:bewege(a, b); } };
Hätte gedacht, das virtuelle Ableitung hier für dieses Problem allgemein bekannt ist.
Optimizer schrieb:
Aber Mehrfachvererbung birngt, wie in dem Beispiel, keine Probleme.
Doch. Du hast alles, was Fortbewegungsmittel jeder Art gemeinsam haben, zweimal geerbt. Herzlichen Glückwunsch, darf ich dir den Diamond of Death persönlich überreichen? Oder willst du mir glauben machen, dass Auto und Boot nichts gemeinsam hätten? Auto und Boot haben schon mal sicher mehr abstrakte Gemeinsamkeiten (Kapazität, Gewicht, Preis, Spritverbrach, Geschwindigkeit, ...) als ein Amphibienfahrzeug mit Boot. Davon mal abgesehen, hat dir die Mehrfachvererbung hier auch keine Vorteile gebracht.
Die "Doppelbelastung" hättest du auch ohne Mehrfachvererbung, nur in einem anderen Level:
class AmphibienFzg : public Auto { Boot boot; }
Oder wie hättest du das gelöst?
-
Optimizer schrieb:
Nehmt zum Beispiel ein GUI-API. Jeder weiß, was ein simpler Button ist und in welchem Kontext er benutzt werden kann. Das einzige, wo da die Vorstellungen noch auseinander gehen könnten ist, kann ein Button Bilder oder andere Steuerelemente enthalten?
Auf jeden Fall ist die Art, wie ein Button sonst verwendet, ziemlich klar. Vielleicht könnte man hier mal versuchen, ein gutes Beispiel zu finden, wo man Mehrfachvererbung nutzbringend einsetzen könnte. Oder kennt jemand ein gutes C++ GUI API mit Mehrfachvererbung?Wer sagt denn, das man um brechen und biegen MV einsetzen soll? Darum geht es hier doch nicht! *kopfschüttel* Nur, ich KANN das einsetzen, wenn ich es für nötig halte.
Wer das Policykonzept anwendet, wird froh sein, das es MV gibt. Ein praktischeren Einsatzzweck kann ich in einem kurzen Satz nicht nennen.
Warum wird eigentlich CaesarJ entwickelt? Konnte mir bisher auch niemand von den Java-Fans beantworten?