"to MI or not to MI"



  • Xin schrieb:

    Eine Klasse Radius darf diese Operationen also nicht öffentlich erben, wenn sie Einschränkungen macht.

    OK. Jetzt verwirrst du mich.
    Kannst du dein Rechteck/Kreis Beispiel dann nochmal herzeigen mit protected Vererbung?

    Weil bis jetzt bin ich von public Vererbung ausgegangen...



  • -.- bitte löschen, danke



  • Xin schrieb:

    Fakt ist, dass ein Klasse, die eine Einschränkung ihrer Basis hat, natürlich nicht public erben darf.

    Und private auch nicht.
    Deswegen schrieb ich mein Beispiel so, daß der Mensch tot wird aus einer Mensch::-Funktion aufgerufen! Auch privat haben wir den Ärger, wenn man Konzepte vermischt. Plötzliches Frühableben ist ehrlich suboptimal.

    Zugegeben, C++ ist schwach und unterstützt native weder Mixins noch Interfaces.

    Du solltest nicht den Fehler begehen, das zu ignorieren. Mach doch Sprachmittel dafür. Du kannst es. Für beide!



  • @Xin: Ich befürchte du missbrauchst Vererbung für eine Art von Typsicherheit die man einfacher, besser und "richtiger benannt" haben kann.
    Ein Quadrat ist nunmal keine Seitenlänge, und genau das sagt aber deine Vererbung aus. Ein Quadart "HAT" eine Seitenlänge, es besitzt eine Seitenlänge.

    Wenn du eigentlich sagen willst, "dieser int ist vom Typ Seitenlänge und hier dürfen damit nur Werte >0 eingetragen werden und ich kann die Seitenlänge nur mit einem expliziten Cast auch als Radius in einen Kreis schreiben" dann willst du nict Vererbung sondern etwas anderes.

    BTW: Mit Vererbung könntest du irgendwie niemals ein Quadrat auf die Seitenlänge eines Radius setzen, oder? Schreibt man da dann tausende Konvertierungs-Operatoren in deiner Sprache?

    Ich hoffe auch, dass die Typsicherheit in Server-lastigen Programmiersprachen (also Sprachen wie Java/C# und auch C++ (client ja erstmal nur noch JS...)) noch weiter erhöht wird. Aber bitte nicht durch Missbauch von Vererbung.

    Da nimmst du ja quasi eine Krücke die dir C++ dafür bieten kann und baust an der Krücke solange außen dran bis sie in deiner Sprache mehr schlecht als recht kann was du willst, obwohl es viel einfachere Möglichkeiten gäbe.

    Ich kann mich leider nicht mehr zu 100% an meine Haskell-Stunden erinnern, aber afaik bietet das Haskell-Typsystem da einige Möglichkeiten die du suchst...

    (Teilweise geschieht dies btw auch schon in Hochsprachen> durch Attributes für Validierung, etc. Teilweise werden asserts() in Konstruktoren geschrieben, usw., aber ja, die "Hochsprachen" sind leider noch nicht ganz bereit dafür)

    MfG SideWinder



  • Shade Of Mine schrieb:

    Der Ctor von Postleitzahl validiert 12345 korrekt und es passt. Nun addiert add aber 700000 drauf und wir haben eine ungueltige Postleitzahl. Was tust du hier um das zu verhindern?

    Irgendwie scheint mir dieses Gegenargument überhaupt nicht zu passen. Eine Programmiersprache oder auch nur Programmierkonzepte hindern einen Entwickler doch nicht daran, dumme Sachen zu machen? Und Postleitzahl von Integer erben zu lassen ist doch eher eine unsinnige Sache. Zumindest kann ich da jetzt nicht erkennen, inwiefern das als Gegenargument dienen soll?
    Da man PLZ niemals addieren wird, macht es auch absolut keinen Sinn, die von Integer erben zu lassen.



  • Abgesehen davon sind längst nicht alle Zahlen zwischen 0 und 99999 valide PLZ.



  • KuhTee schrieb:

    Abgesehen davon sind längst nicht alle Zahlen zwischen 0 und 99999 valide PLZ.

    Logo. Nur die Postleitzahl 0 ist nicht valide, alle anderen Postleitzahlen sind in Ordnung. Denn wir haben den Operator ! von Integer geerbt.
    Und das ist gut so, denn "erstens ist das Einsparen von Schreibarbeit in meinen Augen besser als Schreibarbeit und zum anderen spart es auch "Lesarbeit"" und eine "ausführliche Umfrage", wo viele Leute und wenige Informatiker und erfahrene Programmierte teilnehmen, würde das auch bestätigen. Wir müssen da unbedingt lernen, "unser Verständnis in Frage zu stellen", dann wird alles gut.

    Was Xin braucht, ist wohl

    class Postleitzahl:mixin Integer{
       promote relational;//<, <=, ==, >=, >, !=
       promote std::hash(Integer);//sind ja gute Hashtable-Schlüssel.
       promote constructors, copy, assign;//Jo, die sind ok
       friend ostream& operator<<(ostream& out,Postleitzahl plz);//to be implemented
    }
    

    Ist es überhaupt wahr, zu sagen "Die Postleitzahl IST eine Zahl?"

    "En Dampfmaschin dat is ene jroße schwarze Raum. Der hat hinten un vorn e Loch. Dat eine Loch dat is de Feuerung. Und dat andere Loch dat krieje mer später."
    Ist das denn wahr? IST die Dampfmaschine ein GoßerSchwarzerRaum? IST die Feuerung ein Loch? Oder spielt uns hier die deutsche Sprache nur einen Streich?

    Mir kommt da so ein Verdacht.



  • Shade Of Mine schrieb:

    Xin schrieb:

    Eine Klasse Radius darf diese Operationen also nicht öffentlich erben, wenn sie Einschränkungen macht.

    OK. Jetzt verwirrst du mich.
    Kannst du dein Rechteck/Kreis Beispiel dann nochmal herzeigen mit protected Vererbung?

    Habe ich bisher nie gebraucht, weil das in C++ einfach keinen Spaß mehr macht.

    #include <iostream>
    
    struct Integer
    {
    public:
      int Value;
    };
    
    struct Radius : protected Integer
    {
    public:
      Radius( int radius )
      { *this = radius; }
    
      Radius & operator = ( int radius )
      { Integer::Value = radius < 0 ? 0 : radius; }
    
      Radius & operator -= ( int radius )   // Kann man machen, muss man aber nicht
      { *this = Integer::Value - radius; }
    
      Integer const & AsInteger() const // operator Integer const & mag C++ hier nicht
      { return *this; }
    };
    
    void func( Integer const & value )
    {
      std::cout << value.Value << std::endl;
    }
    
    void manipulateRadius( Radius & r )
    {
      r -= 1000;           // Radius wird negativ
    }
    
    int main( void )
    {
      Radius r( 45 );
    
    //  func( r );  geht nicht
      func( r.AsInteger() );  // => 45
      manipulateRadius( r );  
      func( r.AsInteger() );  // => 0
    }
    

    Das sieht hier alles furchtbar aufwendig und unpraktisch aus - was es in C++ auch ist, weswegen ich es nicht nutze. Dazu zwei Dinge: erstens kann man Code generieren. Schlussendlich macht C++ nichts anderes.
    Es geht hier nicht darum, dass dies ein Feature darstellen soll, sondern die Möglichkeit aufzeigen, dass Dir die Vererbung hier konzeptionell ein Bein stellt: Tut sie nicht, sie ist mit dem Membern gleichwertig.

    Ich würde hier eher von einem UInteger ableiten, bzw. einem PositiveDouble.

    Elementar ist hier operator =(), er repräsentiert gewissermaßen dem Schreibvorgang auf Integer::Value.

    Und bitte versteh den Text da oben jetzt nicht, als etwas, was ich in C++ im Alltag formulieren würde oder gar schön finden würde. Er beschreibt nur einen Pfad, soweit wie man ihn eben in C++ gehen kann.

    Shade Of Mine schrieb:

    Weil bis jetzt bin ich von public Vererbung ausgegangen...

    In C++ sind wir hier auch in einem Bereich, der nicht mehr schön/akzeptabel formulierbar sind. Packt man das aber in eine leicht verständlichere Syntax, sehe ich durchaus Potential.

    volkard schrieb:

    Xin schrieb:

    Fakt ist, dass ein Klasse, die eine Einschränkung ihrer Basis hat, natürlich nicht public erben darf.

    Und private auch nicht.
    Deswegen schrieb ich mein Beispiel so, daß der Mensch tot wird aus einer Mensch::-Funktion aufgerufen! Auch privat haben wir den Ärger, wenn man Konzepte vermischt. Plötzliches Frühableben ist ehrlich suboptimal.

    Dein beschriebenes Verhalten ist in C++ genauso möglich. Ich kann hier nur KuhTee recht geben: Wer scheiße programmiert, wird scheiße erhalten.

    volkard schrieb:

    Du solltest nicht den Fehler begehen, das zu ignorieren. Mach doch Sprachmittel dafür. Du kannst es. Für beide!

    Ich ignoriere das nicht. Und ich bin auch nicht mit allem zufrieden. Aber es entwickelt sich und es ist mir in jedem Fall den Versuch wert.

    SideWinder schrieb:

    @Xin: Ich befürchte du missbrauchst Vererbung für eine Art von Typsicherheit die man einfacher, besser und "richtiger benannt" haben kann.
    Ein Quadrat ist nunmal keine Seitenlänge, und genau das sagt aber deine Vererbung aus. Ein Quadart "HAT" eine Seitenlänge, es besitzt eine Seitenlänge.

    Hatten wir schon. Ein Quadrat kann auch ein SeitenlängenProvider sein. Ich mag diese dogmatische Sicht auf 'ist-ein' und 'hat-ein' nicht sonderlich, denn die Unterscheidung ist nur erforderlich, wenn ein Objekt mehrere Unterobjekte gleicher Art besitzt: Mensch hat zwei Beine. Die beiden Beine sind aber nicht identisch. "hat-ein" und "ist-ein" ist eher die Aussage, ob ein implizierter oder expliziter Cast stattfindet. Deswegen mag ich diese Regel nicht, weil sie ein Lösung anbietet für ein Problem, das falsch formuliert wird - es geht eben nicht um Member oder Vererbung, man baut einen Datensatz zusammen. Mit Membern kann man alles machen, muss sich aber explizit ausdrücken, mit Vererbung kann man einige Bereiche abdecken und hat den Cast implizit.
    Vererbung und Member sind das gleiche: man braucht keine zwei Definitionsmöglichkeiten um einen Datensatz zusammen zu stellen. Man muss klarstellen, ob man ein Objekt implizit zu einem Datentypen umwandeln darf, oder nicht.

    SideWinder schrieb:

    BTW: Mit Vererbung könntest du irgendwie niemals ein Quadrat auf die Seitenlänge eines Radius setzen, oder? Schreibt man da dann tausende Konvertierungs-Operatoren in deiner Sprache?

    Eher die explizite Aufforderung, den Radius in eine Seitenlänge zu interpretieren. Ist ein Radius ein Integer und die Seitenlänge auch, so werden beide einen expliziten Konstruktor für Integer haben. Seitenlänge( radiusObjekt ) ist ein expliziter Wunsch des Entwicklers.

    SideWinder schrieb:

    Da nimmst du ja quasi eine Krücke die dir C++ dafür bieten kann und baust an der Krücke solange außen dran bis sie in deiner Sprache mehr schlecht als recht kann was du willst, obwohl es viel einfachere Möglichkeiten gäbe.

    Nein, ich nutze die Krücke, die mir C++ bietet, um die Gleichheit zu demonstrieren und den impliziten Cast zu nutzen und die Definition von Vererbung auszutesten, wenn es keine gleichartigen Member gibt.

    Nun möchte ich die Sprache so formulieren, dass sie den Entwickler dazu verleitet, diesen Weg mitzugehen und mehr Typen beschreibt.



  • Ich bin noch immer verwirrt.
    Wie genau kann nun Kreis feststellen wann sich sein Radius geaendert hat?

    Wenn ich

    class Kreis : private Radius, private PunktXY {
    public:
      Radius& AsRadius() { return *this; }
    };
    //oder waere
    class Kreis : public Radius, public PunktXY {
    };//korrekter?
    

    schreibe, weiss ich in Kreis ja nicht wann sich Radius geaendert hat.
    Wie wuerde das aussehen wenn ich das wissen will?

    Wenn C++ hier ungeeignet ist, koennen wir auch gerne in Scala oder Ruby modellieren.

    PS:
    Wenn Kreis/Rechteck doof ist, koennen wir auch etwas anderes machen. Solange es etwas grundlegendes ist - damit wir uns nicht in details der Modellierung verlieren. Also zB ein Auto dass einen Motor und 4 Tueren hat und davon Leiten wir dann Sportwagen oder aehnliches ab. Sowas in der Art halt. Nimm dir ruhig irgendein Modell hier mit dem du zufrieden bist.



  • Abgesehen von viel Code um nichts, machste wieder den einen Generalfehler, daß Du nicht programmierst, um folgende Flüchtigkeitsfehler aufzudecken.

    Radius & operator = ( int radius )
    { Integer::Value = radius < 0 ? 0 : radius; }
    

    verdeckt Fehler und macht sie nur schwerer findbar.



  • Fakt ist, dass ein Klasse, die eine Einschränkung ihrer Basis hat, natürlich nicht public erben darf.

    Vererbung hat erstmal nichts mit Zugriffsmodifier zu tun. C++ kann auch ohne public/private funktionieren, genauso kann auch const entfernt werden, ohne das etwas kaputt geht.

    So siehts aus: Allgemeines Konzept -> Umsetzung in einer Sprache. Aber was du machst: Eine Umsetzung in C++ erlaubt deine Idee und du erhebst sie zum allgemeinen Konzept. Leider "funktioniert" es nur unter C++. Doch nicht mehr so allgemein. Ausserdem sind schon sehr viele Probleme angesprochen worden, die vielleicht geloest werden koennen, aber im Vergleich zum traditionellen Vererbungsbegriff eher unelegant wirken.

    Konkret: Kreise erben von Zahlen, Zahlen koennen in unmissverstaendlicher Weise addiert werden und ergeben wieder eine Zahl. Was ist die Addition von zwei Kreisen und ist es wieder ein Kreis? Da gibt es viele Interpretationen.

    Wer scheiße programmiert, wird scheiße erhalten.

    Genau darum geht es. Dein Konzept ist scheisse.



  • Geht es im Kern darum, ob ein Enkel von Eltern und Tanten erben darf
    und einzig die Prämisse im Raum steht
    ob er/sie das Radfahren jetzt vom Onkel oder Vater lernt ?

    Wenn man s rein logisch angeht
    wäre der erste "Lehrer" wohl der Gewinner..



  • Erbt nun bei Deinem Entwurf Wurstbrot von Supermatrkt oder Supermarkt von Wurstbrot?

    Ist ja irgendwie beides richtig.

    class Wurstbrot:Supermarkt {
       //getVerkaufer wird ohne sinnlosen Schreibaufwand geerbt
    }
    

    Aber auch

    class Supermarkt:Wurstbrot {
       //getVerkaufer wird ohne sinnlosen Schreibaufwand geerbt
    }
    

    Hmm.



  • volkard schrieb:

    Erbt nun bei Deinem Entwurf Wurstbrot von Supermatrkt oder Supermarkt von Wurstbrot?

    Das ist der Punkt ^^

    Sowohl das Klima im Supermarkt ändert dein Brot,
    genauso wie dein Brot zum Klima im Supermarkt beiträgt ^^

    Edit:
    Ich denke spätestens wenn Quantencomputer auf den Consumer-Markt drängen,
    wird sich da mit der Vererbung nochmal kräftig was tun.. 🙂
    Alles nur Humbug ?
    Guckst Du hier http://www.dwavesys.com/en/dw_homepage.html
    Abnehmer - Lockheed Martin ..



  • volkard schrieb:

    Nur die Postleitzahl 0 ist nicht valide, alle anderen Postleitzahlen sind in Ordnung. Denn wir haben den Operator ! von Integer geerbt.

    Nein. Nur ein Teil der PLZ sind valide, z.B. ist 00001 keine valide PLZ. Tatsächlich sind ein Großteil der möglichen PLZ nicht in Gebrauch und damit nicht valide. Abgesehen davon gibt es in anderen Ländern "Postcodes" die nicht nur auf Ziffern basieren.

    volkard schrieb:

    Ist es überhaupt wahr, zu sagen "Die Postleitzahl IST eine Zahl?"

    Nein. Darum schrieb ich ja, dass es keinen Sinn macht, PLZ von Integer erben zu lassen.



  • Shade Of Mine schrieb:

    Ich bin noch immer verwirrt.
    Wie genau kann nun Kreis feststellen wann sich sein Radius geaendert hat?

    Das bezog sich nicht auf diese Frage. Bau Dir Events ein, mach, was immer Du unter C++ auch gemacht hast.

    Da ändert sich nix.

    Shade Of Mine schrieb:

    Wenn C++ hier ungeeignet ist, koennen wir auch gerne in Scala oder Ruby modellieren.

    Wir können das gerne, wobei ich das nur gerne könnte. 😉 Meine Scala-Kenntnisse sind überschaubar (ich arbeite dran, wenn ich mal endlich mal wieder Zeit dafür habe) und meine Rubykenntnisse noch viel überschaubarer.

    Das Ganze dreht sich ja auch nicht darum, das hier aufzublähen, sondern die Gleichwertigkeit zu demonstrieren. Dafür habe ich eben einen C++-Code mit reichlich Boilerplate reingepackt, in den kannst Du beim Zuweisungsoperator von Radius reinpacken, was immer Du magst. Beispielsweise jemanden informieren, dass sich der Radius geändert hat.

    Bitte erzähl mir jetzt nicht, dass ich gefälligst <BeliebigeSpracheEinsetzen> lernen soll, damit ich mir angucken kann, wie man das richtig macht. Ich schaue mir regelmäßig neue Sprachen an, wenn ich Zeit dafür habe und jeder hat da seine persönliche Meinung, welche Sprache die richtige ist.

    volkard schrieb:

    Abgesehen von viel Code um nichts, machste wieder den einen Generalfehler, daß Du nicht programmierst, um folgende Flüchtigkeitsfehler aufzudecken.

    Viel Code um nichts. Richtig. Boilerplate. Aber zu inlinen, generierbar (sowas machen Compiler), bzw. nur in C++ erforderlich, um Anweisungen zu forwarden: wenn der Compiler diese Forwards automatisch macht, indem er zum Beispiel direkt die zu rufende Funktion einsetzt, wird da auch tatsächlich wieder "nichts" draus. Nur mit C++ ist das eben nicht formulierbar.

    Du hast vor meinem Posting einen anderes Posting gesetzt, dass ich jetzt erst gesehen habe:

    volkard schrieb:

    Was Xin braucht, ist wohl C++:

    class Postleitzahl:mixin Integer{
       promote relational;//<, <=, ==, >=, >, !=
       promote std::hash(Integer);//sind ja gute Hashtable-Schlüssel.
       promote constructors, copy, assign;//Jo, die sind ok
       friend ostream& operator<<(ostream& out,Postleitzahl plz);//to be implemented
    }
    

    Das ist in der Granularität durchaus gewünscht. Nur müssen die Standardfälle in Kurzform definiert werden können.

    volkard schrieb:

    Radius & operator = ( int radius )
    { Integer::Value = radius < 0 ? 0 : radius; }
    

    verdeckt Fehler und macht sie nur schwerer findbar.

    Sorry, wenn ich um die Uhrzeit nicht mehr alles so optimal hinbekomme.

    Radius & operator = ( Radius radius )
    { Integer::Value = radius.Integer::Value < 0 ? 0 : radius.Integer::Value; }
    

    Führt zu

    Streckenlänge s( 10 );
    Radius r(5);
    
    r = Radius( s );
    

    knivil schrieb:

    Eine Umsetzung in C++ erlaubt deine Idee und du erhebst sie zum allgemeinen Konzept. Leider "funktioniert" es nur unter C++. Doch nicht mehr so allgemein. Ausserdem sind schon sehr viele Probleme angesprochen worden, die vielleicht geloest koennen, aber im Vergleich zum traditionellen Vererbungsbegriff eher unelegant wirken.

    In C++ sind wir hier an einer Stelle, die in C++ ziemlich unelegant ist. Beim SubtypeableOperator hingegen empfinde ich das auch in C++ elegant und angemessen. Nur in solchen Fällen nutze ich Mehrfachvererbung in C++.

    knivil schrieb:

    Wer scheiße programmiert, wird scheiße erhalten.

    Genau darum geht es. Dein Konzept ist scheisse.

    Für C++ sind wir an dieser in einem Bereich, den niemand als "schön" verkaufen will.

    Alle bisher genannten Probleme sind mir bekannt und Lösungen sind in C++ nur teilweise überhaupt zu formulieren und wenn dann sieht das auch durchaus "scheiße" aus. Aber teilweise geht es in C++ und das ist zusammen zu führen, so dass nicht mehr zwischen Membern und Ableitung zu unterscheiden ist, sondern es nur noch eine Form Komposition gibt, die aber pro Element beschreibt, wie damit umgegangen werden soll. Das ganze hier ist ja nicht als Programmierempfehlung für C++ zu verstehen, sondern nur als Richtungszeiger, wohin man denken kann.

    Ihr habt euch hier auf die gleichen Probleme gestürzt wie ich. Ihr mit dem Ziel, mir zu sagen, dass "mein" Konzept scheiße ist und ich mache das mit dem Ziel das Standardproblem umreißen zu können. Und für Standardprobleme muss eine Sprache dann eine Standardlösung anbieten. Wir arbeiten in die gleiche Richtung nur mit unterschiedlicher Motivation: Ihr sagt mir viele Probleme, ich versuche eine Abstraktion dafür zu finden und eine Lösung zu erarbeiten.
    Ich sehe die Chance, dass das klappt, ich sehe da Potential, also probiere ich es aus.

    Zurück zur ursprünglichen Debatte: Beim SubtypeableOperator ist die Mehrfachvererbung, so wie sie in C++ formulierbar ist, hilfreich. Zum einen deswegen halte ich es für sinnvoll, sich mit Mehrfachvererbung auseinander zu setzen und zum anderen halte ich es für sinnvoll, um sich mit dem Konzept der Mehrfachvererbung vertraut zu machen, weil ich davon ausgehe, dass andere Sprachentwickler sich auch Gedanken zu dem Thema machen werden, weil Interfaces eigentlich auch nur ein "scheiß Konzept" sind und sich andere Entwickler auch um Lösungen bemühen.

    Java baut zurück und nennt das Interfaces. Scala wirft Traits in die Arena. Es ist halt viel Ausprobieren und wo am Ende etwas interessantes rauskommt, kann man auch nicht in so einem Thread behandeln, sondern braucht entsprechende Software, um das im Verlauf der Entwicklung dieser Software zu beobachten, was sich wirklich als praktisch erweist, wo etwas nur im Beispiel praktisch aussieht, aber wieder entfernt werden sollte oder wo sich vielleicht Möglichkeiten ergeben, die weiter aufgebaut werden können.

    Trotzdem ist dieser Thread für mich hilfreich, wenn man vielleicht mal von volkard, pVoid und ihrem Wurstbrot absieht, denn auch wenn ich noch nichts gelesen habe, was mir neu wäre, so zwingt es mich, die Sachen in Frage zu stellen und damit zu verifizieren.
    Bisher denke ich weiterhin, dass es ein guter Versuch ist. Und wenn nicht, bleibt trotzdem Subtypable und Operator als Grund für Mehrfachvererbung.



  • Xin schrieb:

    volkard schrieb:

    Radius & operator = ( int radius )
    { Integer::Value = radius < 0 ? 0 : radius; }
    

    verdeckt Fehler und macht sie nur schwerer findbar.

    Sorry, wenn ich um die Uhrzeit nicht mehr alles so optimal hinbekomme.

    Radius & operator = ( Radius radius )
    { Integer::Value = radius.Integer::Value < 0 ? 0 : radius.Integer::Value; }
    

    Führt zu

    Streckenlänge s( 10 );
    Radius r(5);
    
    r = Radius( s );
    

    Facepalm.
    Das Überdecken den Programmierfehlers r-=1000, Du Nase. Das "< 0 ? 0" ist ärgeranziehend.

    Ganz so, wie übrigens Deine falsch angewendete Vererbung auch. Eines der Hauptprobleme scheinz zu sein, daß Du überhaupt kein Gefühl für defensives Programmieren zu haben scheinst. Nur Tipparbeit sparen zu wollen, ist einfach kein guter Ratgeber.
    Schade, daß Du aufs umdrehen-Beispiel nicht eingehen magst.



  • Xin schrieb:

    Shade Of Mine schrieb:

    Ich bin noch immer verwirrt.
    Wie genau kann nun Kreis feststellen wann sich sein Radius geaendert hat?

    Das bezog sich nicht auf diese Frage. Bau Dir Events ein, mach, was immer Du unter C++ auch gemacht hast.

    Da ändert sich nix.

    Aber OK, du würdest hier also ein Notification System einbauen. Das kann man ja wiederum erben.
    Ich habe das ganze dann mal eben geschrieben:
    http://ideone.com/hHs59f

    Ist das so in etwa das was du dir vorstellst?
    C++ wehrt sich da irgendwie mit Händen und Füßen dagegen...

    Gibt es eine Sprache wo das etwas besser geht, weil - ohne dass du das jetzt bitte falsch verstehst - in C++ ist das nicht möglich so zu programmieren. Ich muss konstant Code verdoppeln und muss höllisch auf die Scopes aufpassen weil da dauernd irgendein Parent reinpfuscht.

    Mir ist egal welche Sprache. Such dir eine aus. Hauptsache es gibt Tutorials zum einlesen - dann gib mir ein paar Tage und wir können mit der Sprache weiter diskutieren.

    Falls wir bei C++ bleiben, dann habe ich gleich eine Frage:
    Kann man den op= irgendwie besser aufrufen als über die Qualifizierung des Ursprungstyps. ein
    k.Radius::operator=() ging leider nicht.

    uU habe ich ja auch was falsch gemacht - deshalb, wenn möglich - kannst du meinen Code ausbessern?

    Das Ganze dreht sich ja auch nicht darum, das hier aufzublähen, sondern die Gleichwertigkeit zu demonstrieren. Dafür habe ich eben einen C++-Code mit reichlich Boilerplate reingepackt, in den kannst Du beim Zuweisungsoperator von Radius reinpacken, was immer Du magst. Beispielsweise jemanden informieren, dass sich der Radius geändert hat.

    Boilerplate ist mir egal. Boilerplate ist nur Syntax. Wichtig ist, dass wir korrekt modellieren können.



  • volkard schrieb:

    Facepalm.
    Das Überdecken den Programmierfehlers r-=1000, Du Nase. Das "< 0 ? 0" ist ärgeranziehend.

    Ich baue hier kein perfektes Framework für geometrische Objekte auf. Das hier sind kurzgehaltende Beispiele, um eine Richtung anzudeuten, keine Programme, die Du danach als ein CAD kompilieren kannst. Es geht um Unterscheidungen - mir jedenfalls - nicht darum in einem speziellen Fall die perfekte Implementierung für eine Unterscheidung hier abzuliefern.
    Irgendwann muss so ein Posting auch mal fertig werden und falls dann etwas Unwichtiges nur irgendwie kompilierfähig gemacht wird, dann kannst Du Dir das sicherlich auch selbst kurz in Hübsch vorstellen.

    volkard schrieb:

    Ganz so, wie übrigens Deine falsch angewendete Vererbung auch. Eines der Hauptprobleme scheinz zu sein, daß Du überhaupt kein Gefühl für defensives Programmieren zu haben scheinst. Nur Tipparbeit sparen zu wollen, ist einfach kein guter Ratgeber.
    Schade, daß Du aufs umdrehen-Beispiel nicht eingehen magst.

    Weil es nichts mit Mehrfachvererbung zu tun hat, weil darauf bereits eingegangen wurde, weil der Fehler problemlos zu debuggen ist, weil die Hierarchie semantisch verifizierbar ist, wenn die Sprache das unterstützt, weil der Funktionsname schon scheiße gewählt ist, weil das Beispiel Schwachsinn ist, denn wer erlaubt, dass sich ein Kopf vier mal um 90 Grad umdrehen lässt, der tötet einen Menschen weil er eine Restriktion im Hals falsch implementiert (Hallo defensives Programmieren!) hat und nicht weil er vergessen hat den Menschen am richtigen Punkt umzudrehen, weil Du Fehler allgemein nicht grundsätzlich abfangen kannst und Du Deine Software erstmal mit einem Dummy testen musst, bevor Du einen Menschen damit fernsteuerst und das ganz normaler Entwicklungsalltag ist und Du den Fehler mit Membern genauso beschreiben kannst.

    Die Tatsache, dass man auch fehlerhafte Programme formulieren kann, weil man etwas anderes wünscht, als man geschrieben hat ist als Argument einfach Schwachsinn.

    Darum testet man Software im Idealfall und bringt dann erst Menschen damit um. (Sarkasmus-Schild-Hochhaltend)

    @Shade: Dafür das mit Dir durchzugehen, möchte ich mir mehr Zeit nehmen, damit ich den Code auch mal durch den Compiler jagen kann.

    Ich kann Dir nicht sagen, ob es dafür eine Sprache gibt, mir ist keine bekannt, sonst würde ich die ja verwenden und nicht selbst eine schreiben. ^^
    Kann ich die Probleme sprachlich einkreisen, kann ich sie auch (hoffentlich) sprachlich lösen. Wenn nicht oder sich das Ganze im praktischen Einsatz nicht als gut bewährt... dann Arschkarte. 😉

    Ich kann Dir allerdings nicht sagen, wann ich Ruhe dafür habe und die Zeit, Probleme in C++ zu formulieren, die ich so üblicherweise auch nicht in C++ formulieren würde.
    Ich habe jetzt keine Zeit dafür und ehrlich gesagt auch keinen Plan, ob oder wann ich diese Woche überhaupt noch Zeit für irgendwas habe. Sehr wahrscheinlich eben nicht, um mich in Ruhe und idealerweise auch mal ausgeschlafen an irgendeinen Compiler zu setzen.

    Shade Of Mine schrieb:

    Boilerplate ist mir egal. Boilerplate ist nur Syntax. Wichtig ist, dass wir korrekt modellieren können.

    Gute Basis. 🙂

    PS: Verdammt... bin zu neugierig... ich habe nochmal über den Code geguckt und fand das unten abgedruckte Ergebnis eigentlich doch so entsprechend meiner Erwartung.
    Entsprechend hast Du C++ offenbar ja doch gebändigt bekommen, obwohl es sich gewehrt hat. 😉

    Shade Of Mine schrieb:

    Falls wir bei C++ bleiben, dann habe ich gleich eine Frage:
    Kann man den op= irgendwie besser aufrufen als über die Qualifizierung des Ursprungstyps. ein
    k.Radius::operator=() ging leider nicht.

    Warum nicht?

    Hier werden vermutlich zwei Anpassungen gleichzeitig nötig sein, weswegen C++ streikt. Ich würde Radius::operator 😞 Radius const & r ) definieren und weiterleiten.

    Es reicht vermutlich reicht aber auch

    k.Radius::operator=( Radius( 7 ) );
    

    (Nicht ausprobiert, just an educated guess)



  • Xin schrieb:

    Weil es nichts mit Mehrfachvererbung zu tun hat,

    Irgendwie schon. Weil Vererbung bereits falsch ist, ist Mehrfachvererbung mehrfach falsch.


Anmelden zum Antworten