Mehrfachvererbung



  • 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?



  • Artchi schrieb:

    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?

    Für Policies ist es in der Tat nützlich, wobei man hier auch sagen könnte das
    man mit Interfaces das selbe mit mehr Arbeit erreichen kann.

    Wobei ich mich allerdings wunder, ist das ausser dem Beispiel mit dem
    Amphibienfahrzeug (über dessen sinn sich vortrefflich Streiten lässt 🤡 )
    noch kein weiteres genannt wurde. Evtl. mal eins was sich auch in der Praxis anwenden lässt 😉

    phlox



  • Artchi schrieb:

    Warum wird eigentlich CaesarJ entwickelt? Konnte mir bisher auch niemand von den Java-Fans beantworten?

    Ich kann Dir sagen, warum Dir das keiner beantwortet: Das interessiert keinen. Und schon gar keinen "Java-Fan". Mir persönlich ist dieses Projekt völlig unbekannt, obwohl ich eigentlich regelmäßig die großen Java-Seiten im Netz abklappere. Wenn dieses Projekt in der Java Welt irgendeine Bedeutung hätte, würde es auch hin und wieder auf diesen Seiten erwähnt werden.

    Mit anderen Worten: CaesarJ scheint halt so ne Idee von irgendeiner Randgruppe oder so zu sein. ...und nur weil da irgendeine Uni oder ne größere Firma mit zu tun hat, ändert sich das noch lange nicht.

    Zusatz: Insgesamt scheint sich in der Java-Welt fast keiner für Mehrfachvererbung zu interessieren. Wenn irgendwelche Forderungen nach bestimmten Sprachfeatures aufkommen, sind das andere Features. "const" war zum Beispiel mal sehr begehrt. "Operator Overloading" ist auch hin und wieder im Gespräch. ...und genauso sind auch einige andere Features manchmal im Gespräch, die andere Sprachen, wie zum Beispiel C++, bieten. Es sind ja damals mit Java 5.0 auch einige Features dazugekommen, die teilweise öfter mal nachgefragt wurden. ...naja: Zumindest ist "Mehrfachvererbung" einfach nicht bei den Features dabei, die nachgefragt werden.

    Zusatz 2: Top 25 RFEs: http://bugs.sun.com/bugdatabase/top25_rfes.do



  • Artchi schrieb:

    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. 🙄

    Was bringt dieses "Gefrickel" jetzt? Für mehrere Methoden schreibst du dann sucheTankstelle -> sucheTankMöglichkeit, sucheBootshafen -> sucheTankMöglichkeit und hast jedesmal geile Methoden, die nur delegieren, hundertfach. Das sieht nur bei einer vererbten Methode noch akzeptabel aus. Du hast zwei zusätzliche Basisklassen, die keiner wollte. Sind das die großen Vorteile der Mehrfachvererbung?

    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?

    Man darf keine Komposition aus Auto und Boot bauen, denn AmphibienFzg enthält ja kein Auto und kein Boot. Ebenso wäre es ein Designfehler, AmphibienFzg von Auto abzuleiten, wenn es sich nicht in jeder Hinsicht wie ein Auto verhält. Dast ist natürlich programmabhängig. In GTA versinken Autos im Wasser, dort dürfte man ein AmphibienFzg nicht von Auto ableiten.

    Der Kern ist, dass man eigentlich nur etwas Verhalten von Auto und Boot haben möchte. Dieses Verhalten kann man verallgemeinern und in Klassen ausmodellieren. Ich kann mir sowas vorstellen:

    class AmphibienFzg : Vehicle {
        SharedLandfahrzeugBehaviour land;
        SharedWasserfahrzeugBehaviour water;
    }
    

    So schafft man sich kleine Bauteile, aus denen man wie mit Legosteinen verschiedene Land-, Wasser-, und Luft-Fahrzeuge zusammenbauen kann:

    class Boat : Vehicle {
        SharedWasserfahrzeugBehaviour water;
    }
    
    class Car : Vehicle {
        SharedLandfahrzeugBehaviour land;
    }
    

    Mögliche Codeduplizierung beschränkt sich jetzt auf das LandfahrzeugBehaviour einbinden sowohl in Auto als auch in Amphib. - ein Einzeiler. Unter manchen Umständen kann es auch noch akzeptabel sein, protected Methoden aus der Basisklasse nur in manchen abgeleiteten Klassen öffentlich zugänglich zu machen. In C++ kann man zusätzlich private Vererbung bemühen.

    Aber niemals öffentlich ableiten, wenn nicht das Verhalten völlig passend ist, wie wahrscheinlich in den meisten Szenarien mit Auto und Amphib.

    Konkreter kann ich jetzt nicht werden, da wir - wie gesagt - kein vernünftiges Szenario haben.



  • 1310-Logik schrieb:

    Das Beispiel ist doch falsch.
    Ein AmphibienFz steht doch hierarchisch auf der selben Ebene wie Auto und Boot, erbt also nur von Fahrzeuge gemeinsames.

    Korrekt. "Amphibienfahrzeug" ist keineswegs ein konkreterer Begriff als Auto. Eher ist Auto noch was konkreteres, nämlich ein Ableitung von Landfahrzeug. Du hast genau den entscheidenden Punkt genannt.



  • Sehe ich nicht so.
    "Amphibienfahrzeug" (ebenso wie Auto, Fahrrad, Dreirad, Roller)
    ist eine Verfeinerung von "Fahrzeug" und gleiochzeitig eine Verfeinerung von "Boot", (gleichrangig neben Ruderboot, Dampfschiff, Kreuzer). "Amphibienfahrzeug" steht also hierarchisch auf derselben Stufe wie "Auto" (direkt abgeleitet von "Fahrzeug") und "Paddelboot" (direkt abgeleitet von "Boot").

    Das Beispiel "Amphibienfahrzeug" ist tatsächlich eine Anwendung, wo Mehrfachvererbung die nächstliegende Möglichkeit ist.

    Ciao



  • Entschuldige, meine Basisklasse war schlecht benamst. Müsste "Fortbewegungsmittel" heissen...

    Das ein Amphi. kein Auto ist, muss einleuchten, es ist auch kein Auto mit erweiterter funktionaluität. Es ist eben ein Spezialfahrzeug. Ein Panzer ist auch kein Auto, oder?


Anmelden zum Antworten