Mehrfachvererbung in dem Fall angemessen?



  • Hi,
    Von Mehrfachvererbung insbesondere mit Implementierung der Funktionen wird ja häufig abgeraten, deswegen habe ich hier mal eine kleine Designfrage.

    Welche Kritik könnte man an folgender an Scala angelehnten Klasse anbringen, da diese ja völlig unabhängig von der eigentlichen Klassenhierarchie existiert wäre Mehrfachvererbung hier sicher nicht ausgeschlossen:

    template <typename T>
    class ordered
      {
      public:
        bool operator<(T const& that);
        bool operator<=(T const& that);
        bool operator==(T const& that);
        bool operator!=(T const& that);
        bool operator>=(T const& that);
        bool operator>(T const& that);
      private:
        virtual int compare(T const& that) = 0;
      };
    
    template <typename T>
    bool ordered<T>::operator<(T const& that)
      {
      if(compare(that) < 0)
        return true;
      return false;
      }
    
    template <typename T>
    bool ordered<T>::operator<=(T const& that)
      {
      if(compare(that) <= 0)
        return true;
      return false;
      }
    
    template <typename T>
    bool ordered<T>::operator==(T const& that)
      {
      return !compare(that);
      }
    
    template <typename T>
    bool ordered<T>::operator!=(T const& that)
      {
      return !(*this == that);
      }
    
    template <typename T>
    bool ordered<T>::operator>=(T const& that)
      {
      return !(*this < that);
      }
    
    template <typename T>
    bool ordered<T>::operator>(T const& that)
      {
      return !(*this <= that);
      }
    

    Wäre so etwas sinnvoll? Könnte man es in C++ auf eine andere Art besser implementieren?



  • versuch mal die concepts http://en.wikipedia.org/wiki/C%2B%2B0x#Concepts von c++ zu verstehen. ich glaube, die passen da besser.
    wenn dem so ist, sag nochmal hier bescheid.



  • concepts gibts doch noch gar nicht?
    Zudem beschränken sich concepts doch auf Templateparameter, oder?
    Das hier wäre doch allgemeiner, es bietet alle Vergleichsoperatoren auf Basis einer comparefunktion.



  • JustAnotherNoob schrieb:

    Von Mehrfachvererbung insbesondere mit Implementierung der Funktionen wird ja häufig abgeraten, deswegen habe ich hier mal eine kleine Designfrage.

    Ich gehe jetzt nur auf die Problematik als solche ein (Für die Klasse müsste ich mir mehr Zeit nehmen):

    Vor Mehrfachvererbung wird in der Tat abgeraten, nur gibt es gerade im C++ Templatebereich einige Ausnahmen wo es dennoch sehr sinnvoll ist. Als Beispiel nenne ich hier mal die "Trait class", zum Beispiel geht Andrei Alexandrescu in seinen Buch "Modern C++ Design" darauf ein (Die extrem konfigurierbaren Smartpointer der Loki-Bibliothek sind zum Beispiel als solchen zusammengesetzt). In sofern ist dein Konzept nicht unbedingt verkehrt.



  • http://www.boost.org/doc/libs/1_38_0/libs/utility/operators.htm

    Das ganze geht auch ohne virtuelle Methode.
    Aber im Prinzip ist hier mehrfachvererbung natürlich OK.

    man sagt ja nur mehrfachvererbung sei schlecht, damit die leute nachdenken wann sie erben. weil sonst hast du sowas wie in java, dass du von zig millionen klassen erbst und denkst dass das so passt...



  • Shade Of Mine schrieb:

    man sagt ja nur mehrfachvererbung sei schlecht, damit die leute nachdenken wann sie erben.

    eher deshalb: http://en.wikipedia.org/wiki/Diamond_problem
    🙂



  • +fricky schrieb:

    Shade Of Mine schrieb:

    man sagt ja nur mehrfachvererbung sei schlecht, damit die leute nachdenken wann sie erben.

    eher deshalb: http://en.wikipedia.org/wiki/Diamond_problem
    🙂

    das hast du nur wenn du nicht nachdenkst...



  • Shade Of Mine schrieb:

    das hast du nur wenn du nicht nachdenkst...

    Das ist aber das einzige mir bekannte Problem von Mehrfachvererbung (Die du in dieser Form in Java garnicht hast), was du ansprichst ist die Vererbungstiefe (Die hast du aber auch bei normalen Ableitungen). Nachdenken ist bei beiden angebracht.



  • asc schrieb:

    Das ist aber das einzige mir bekannte Problem von Mehrfachvererbung

    struct A { void f() {} };
    struct B { void f() {} };
    struct C : A,B {};
    C c;
    c.f();
    

    vorallem wenn f noch virtual ist, etc.

    gibt viele probleme - aber deshalb muss man überlegen ob vererbung sinn macht. meistens ist vererbung nämlich das falsche mittel. siehe java und listeners. vererbung ist hier falsch...



  • Shade Of Mine schrieb:

    siehe java und listeners. vererbung ist hier falsch...

    Warum?



  • ihoernchen schrieb:

    Shade Of Mine schrieb:

    siehe java und listeners. vererbung ist hier falsch...

    Warum?

    Genau das meine ich 😉

    Es bläht einfach die Klasse auf, verschmutzt das Interface und bricht die kohäsion. mal von den generellen problemen von mehrfachvererbung abgesehen.

    Java hat für sowas anonyme Klassen. (mal abgesehen davon dass das listener konzept in java nicht wirklich toll ist).

    Vererbung ist einfach fast immer die falsche Lösung zu einem Problem.



  • Wie löst du das, wenn du so eine Beziehung zwischen Objekten hast? Also Objekte die auf Nachrichten von anderen Objekten warten?



  • anonyme klassen.

    sagen wir du hast ein fenster mit einem button und nun willst du abfangen wann der button gedrückt wird. dann packst du in den button einen anonymen listener der mir vom fenster dann die passende methode "veryImportantButtonClicked" aufruft. das ist vorallem dann recht praktisch wenn ich 2 buttons habe auf deren onClick ich reagieren will...

    und im code selber ist es natürlich schöner lesbar wenn da steht was nun geclickt wurde...

    uU kann auch triviale logik in der anonymen klasse stehen. zB dass das event nicht gefeuert wird wenn der receiver in einem bestimmten zustand ist, etc.



  • Shade Of Mine schrieb:

    dann packst du in den button einen anonymen listener der mir vom fenster dann die passende methode "veryImportantButtonClicked" aufruft.

    Wie meinst du das konkret? So in der Art?:

    button.OnClick = new Listener { public void OnClick() {
        wnd.veryImportantButtonClicked();
        } }
    


  • Badestrand schrieb:

    Shade Of Mine schrieb:

    dann packst du in den button einen anonymen listener der mir vom fenster dann die passende methode "veryImportantButtonClicked" aufruft.

    Wie meinst du das konkret? So in der Art?:

    button.OnClick = new Listener { public void OnClick() {
        wnd.veryImportantButtonClicked();
        } }
    

    ja.

    bzw. kann natürlich auch etwas logik hier stehen...

    PS:
    nur dass du ja kein OnClick in java hast sondern ein
    registerFooBarListener()
    😉

    PPS:
    mit OnClick bzw. richtigen callbacks/delegates ist das problem natürlich komplett gelöst 😉



  • Shade Of Mine schrieb:

    Badestrand schrieb:

    Shade Of Mine schrieb:

    dann packst du in den button einen anonymen listener der mir vom fenster dann die passende methode "veryImportantButtonClicked" aufruft.

    Wie meinst du das konkret? So in der Art?:

    button.OnClick = new Listener { public void OnClick() {
        wnd.veryImportantButtonClicked();
        } }
    

    ja.

    bzw. kann natürlich auch etwas logik hier stehen...

    PS:
    nur dass du ja kein OnClick in java hast sondern ein
    registerFooBarListener()
    😉

    PPS:
    mit OnClick bzw. richtigen callbacks/delegates ist das problem natürlich komplett gelöst 😉

    delegates ist genau das gleiche wie die Listeners in Java. Anstelle dass du

    button.OnClick += new Listener() {...};
    

    schreibst, hast du halt ein

    button.addActionListener(new Listener() {...});
    

    🤡 🤡



  • Ich weiss nicht, ob ich das richtig verstanden habe. Du schiebst nur eine weitere Ebene zwischen Listener und eigentliche Klasse (die innere/anonyme Klasse)?

    class Fenster
    {
      class FensterListener : Listener
      {
        public: void OnEvent()  {fenster->Click();}
        private: Fenster* fenster;
      }
    
      private: void Click() {}
    }
    // und im Fenster eben irgendwo RegisterListener(fensterListenerObject)
    

    Mh. Das finde ich nicht unbedingt besser oder schöner. Ok, du hast die Listener Methoden aus der Fenster Schnittstelle entfernt. Im Gegenzug aber eine weitere Ebene eingeführt.

    Die anonymen Klassen finde ich nicht gut. Da sammelt sich gerne irgendwann mal alles mögliche an und es wird unübersichtlich.



  • Shade Of Mine trollt mal wieder mit seinem Halbwissen rum! 🙄 👎



  • Es ist völlig egal, ob es anonmye oder nichtanonyme Listener-Klassen sind. Hauptsache, man lässt die "Hauptklasse" nicht alle möglichen Interfaces implementieren, um dann in riesigen if-Kaskaden auf Events zu reagieren. Das durchbricht die Kapselung und verletzt das Geheimnisprinzip.
    Davon abgesehen ist es in Java eher üblich, Actions oder Models einzusetzen, als nackte Listener.

    bzw. richtigen callbacks/delegates ist das problem natürlich komplett gelöst

    Warum Delegates (a la C#) doch nicht so unproblematisch sind, kann man hier nachlesen.



  • DEvent schrieb:

    delegates ist genau das gleiche wie die Listeners in Java.

    dh, du erbst immer von delegates.

    alles klar.

    bitte thread lesen 😕

    und tfas post lesen, der bringts auf den punkt


Anmelden zum Antworten