"to MI or not to MI"



  • Wie genau verhinderst du jetzt dass ich den Radius von einem Kreis negativ setze?



  • Shade Of Mine schrieb:

    Wie genau verhinderst du jetzt dass ich den Radius von einem Kreis negativ setze?

    <sarcasm>
    Ich glaube, Du hast da ein wesentliches K.O. Kriterium erkannt.

    Man kann auch keinen Kaffee damit kochen. Ich glaube, ich sollte die Programmierung aufgeben, wenn's nichtmals Kaffee kochen kann.
    </sarcasm>

    PS: Wenn das jetzt ernsthaft die schärfste Kritik von Dir war, die Dir für dieses Beispiel eingefallen ist, dann kann ich so falsch ja gar nicht liegen.



  • Ich fang an zu glauben, dass Xin prädikativ Typen will wie in Cecil.



  • Xin schrieb:

    PS: Wenn das jetzt ernsthaft die schärfste Kritik von Dir war, die Dir für dieses Beispiel eingefallen ist, dann kann ich so falsch ja gar nicht liegen.

    Es ist eine ernste Frage.
    Ich stelle sie mal allgemeiner: wie garantierst du Invarianten?

    Wenn Postleitzahl von Integer erbt, wie beschraenke ich Postleitzahlen auf 0 bis 99999 ? Oder woher weiss der Kreis, dass sich sein Ursprung geaendert hat um sich neu zuzeichen? Etc.



  • Zeus schrieb:

    Ich fang an zu glauben, dass Xin prädikativ Typen will wie in Cecil.

    Cecil? Da finde ich Damenmode!? ^^

    Habe noch eine Mono-Library gefunden.

    Shade Of Mine schrieb:

    Es ist eine ernste Frage.
    Ich stelle sie mal allgemeiner: wie garantierst du Invarianten?

    Wie garantiere ich Invarianten mit Membern?

    Wenn ich einem Kreis ein double als Radius mitgebe, wie garantiere ich da, dass der Kreis einen positiven Radius besitzt?

    Shade Of Mine schrieb:

    Wenn Postleitzahl von Integer erbt, wie beschraenke ich Postleitzahlen auf 0 bis 99999 ?

    In dem Fall muss ich wohl für PLZ einen Konstruktor schreiben, der das verifiziert und eine Initialisierung mit unzulässigen Werten ggfs. ablehnt, wie ich für Radius auch tun müsste, wenn ich ein Problem mit negativen Radien habe.

    Ich sehe hier keinen Unterschied zur Initialisierung von Membern in der Initialisierungsliste - und, je nach Implementierung auch nicht im Konstruktor der Address-Klasse.

    Shade Of Mine schrieb:

    Oder woher weiss der Kreis, dass sich sein Ursprung geaendert hat um sich neu zuzeichen? Etc.

    Auch hier sehe ich das Problem erstmal nicht im Aufbau der Datentypen, Du kannst genauso Events verwenden oder eben den Zugriff auf den Schreibzugriff von Punkt im Grafikobjekt erstmal abfangen. Das wäre allerdings in C++ wieder nicht formulierbar, ohne dass man überladbare Methoden hat. Ich selbst mache zwischen Getter- und Setter-Funktionen und dem direkten Zugriff auf Variablen keinen so großen Unterschied.

    Aber es gibt vermutlich noch eine weitere vorstellbare Lösung, die in C++ aber gar nicht formulierbar ist und ich bei mir noch nicht ausprobieren konnte. Soweit ist meine Sprache leider noch nicht. Vielleicht kann ich dazu Ende des Jahres was sagen.



  • Xin schrieb:

    Shade Of Mine schrieb:

    Wenn Postleitzahl von Integer erbt, wie beschraenke ich Postleitzahlen auf 0 bis 99999 ?

    In dem Fall muss ich wohl für PLZ einen Konstruktor schreiben, der das verifiziert und eine Initialisierung mit unzulässigen Werten ggfs. ablehnt, wie ich für Radius auch tun müsste, wenn ich ein Problem mit negativen Radien habe.

    Hier sehe ich zwei Probleme. Das erste ist sowas (Pseudocode):

    func(Integer& i1, Integer i2) {
        i1 -= i2;  // gültig und definiert für Integer
    }
    
    func(kreis1.radius, kreis2.radius); // huch, plötzlich Fehler, obwohl ein Radius ein Integer ist
    

    Radius ist hier Integer statt Double der Einfachheit halber, das Argument ist dasselbe.
    Das Problem hat man mit Membern nicht, da bei

    kreis1.setRadius(kreis1.getRadius() - kreis2.getRadius())
    

    eben nicht garantiert ist, dass das keinen Fehler wirft, im Gegensatz zum -= bei Integern.

    Das zweite ist, dass es bei deiner Klassenhierarchie ja eigentlich heißen müsste:

    func(kreis1, kreis2)
    

    Aber welcher Integer beim Kreis ist denn gemeint? Radius, Durchmesser, Umfang? Gut, hier könnte man es sich eventuell denken, aber was ist beim Rechteck?
    Das „is-a“, was immer so runtergebetet wird, hat ja einen Grund: A is-a B ⇒ A kann wie ein B behandelt werden. Und ich sehe hier nicht, dass ich einen Kreis oder ein Rechteck wie einen Integer behandeln kann.



  • Xin schrieb:

    In dem Fall muss ich wohl für PLZ einen Konstruktor schreiben, der das verifiziert und eine Initialisierung mit unzulässigen Werten ggfs. ablehnt, wie ich für Radius auch tun müsste, wenn ich ein Problem mit negativen Radien habe.

    Ich sehe hier keinen Unterschied zur Initialisierung von Membern in der Initialisierungsliste - und, je nach Implementierung auch nicht im Konstruktor der Address-Klasse.

    Was wenn ich jetzt aber:

    void add(Integer& lhs, Integer& rhs) {
      lhs+=rhs;
    }
    
    Postleitzahl plz(12345);
    add(plz, 700000);
    

    schreibe?

    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?

    In Postleitzahl kannst du den operator+= fuer Integer ja nicht neu definieren - es sei denn der waere virtual. Ist er das?

    Bzw: wie verhinderst du, dass ich Sachen mache die keinen Sinn ergeben: zB eine Postleitzahl mit einer Telefonnummer zumultiplizieren?

    Mich interessiert dabei die Umsetzung in C++ (wir koennen uns auch gerne auf eine andere Sprache einigen). Deine Sprache wuerde ich aus der Diskussion lieber raus lassen, da es keine Sprache ist die wir beide kennen.



  • ipsec schrieb:

    Xin schrieb:

    Shade Of Mine schrieb:

    Wenn Postleitzahl von Integer erbt, wie beschraenke ich Postleitzahlen auf 0 bis 99999 ?

    In dem Fall muss ich wohl für PLZ einen Konstruktor schreiben, der das verifiziert und eine Initialisierung mit unzulässigen Werten ggfs. ablehnt, wie ich für Radius auch tun müsste, wenn ich ein Problem mit negativen Radien habe.

    Hier sehe ich zwei Probleme. Das erste ist sowas (Pseudocode):

    func(Integer& i1, Integer i2) {
        i1 -= i2;  // gültig und definiert für Integer
    }
    
    func(kreis1.radius, kreis2.radius); // huch, plötzlich Fehler, obwohl ein Radius ein Integer ist
    

    Radius ist hier Integer statt Double der Einfachheit halber, das Argument ist dasselbe.

    Das Argument ist sehr gut und bekannt.

    Fakt ist, dass ein Klasse, die eine Einschränkung ihrer Basis hat, natürlich nicht public erben darf. Ein Kreis mit einem öffentlichen Member double Radius kann auch zerlegt werden und zwar genauso, wie Du es beschrieben hast. Es gilt also Inhalt von Integer zu schützen.

    Eine Klasse Radius darf diese Operationen also nicht öffentlich erben, wenn sie Einschränkungen macht. Im Prinzip ist das eine protected Ableitung mit einem operator Integer & const(). Radius darf Integer modifizieren, externe haben kein Zugriffsrecht. Du kannst zum Beispiel einen (Integer const &) zurückgeben, aber den bekommst Du nicht mit dem -= Operator verbogen. Also entweder beschreibst Du in Radius, was Du mit dem Radius machen darfst oder Du kannst ihn nicht in eine Funktion packen,

    ipsec schrieb:

    Das zweite ist, dass es bei deiner Klassenhierarchie ja eigentlich heißen müsste:

    func(kreis1, kreis2)
    

    Aber welcher Integer beim Kreis ist denn gemeint? Radius, Durchmesser, Umfang? Gut, hier könnte man es sich eventuell denken, aber was ist beim Rechteck?

    Auch ein schöner Punkt, der aber durchaus auch in C++ bekannt und gelöst ist. Wenn Du das in C++ so formulierst, wird Dir C++ sagen, dass er eben auch nicht weiß, welchen Integer er hier jetzt reinwerfen soll. Da die Funktion nicht klar festlegt, welchen Integer sie wünscht, also ob Radius, Durchmesser oder Umfang, muss sie ja so allgemein gehalten sein, dass ihr ein beliebiger Integer zur Verarbeitung reicht.
    Und da haben wir natürlich Auswahl und müssen uns selbst festlegen.
    In C++ müsstest Du Dich über ein Casting eindeutig ausdrücken. Da sieht in C++ unschön aus, ist aber an der Stelle das Gleiche wie this->Radius: eine Addition auf die Adresse auf die this zeigt.

    ipsec schrieb:

    Das „is-a“, was immer so runtergebetet wird, hat ja einen Grund: A is-a B ⇒ A kann wie ein B behandelt werden. Und ich sehe hier nicht, dass ich einen Kreis oder ein Rechteck wie einen Integer behandeln kann.

    Bitte die Bibel weglegen und das beten einstellen. Die Gedanken sind frei! 😉

    "is-a" ist nur ein Konzept, dass mit Vererbung beschrieben wird. Stell Dir Kreis als Ableitung von RadiusInterface vor. Damit ist Kreis ein "GetRadiusFunctionProvider" und das wiederum ist ein Integer. Und jetzt lassen wir den ganzen Unsinn weg wieder und sagen "einfach":

    printInteger( this->Radius::Value );
    oder
    printInteger( this->Umfang::Value );

    Wohlgemerkt: Das ist C++... die Sprache, die für Member ausgelegt ist und ich behaupte, dass Mehrfachvererbung und Member erstmal beide die gleiche Aufgabe erfüllen. Das heißt nicht, dass die Syntax in C++ wunderschön ist, noch dass ich ausschließlich alles public machen will. Ich will nur Vorteile von Mehrfachvererbung allgemeiner nutzen.

    Trotzdem: das war bisher eins der besten Postings, die zu dem Thema jemals gekommen sind.



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


Anmelden zum Antworten