OOP: soll man jetzt alles in ne Klasse packen oder watt?



  • fyi schrieb:

    gurkenesser schrieb:

    Klassen sind Funktionsgruppen.
    Beispielsweise sämtliche Sachen, die mit Textdateien in einem Textprogramm zu tun haben könnten in eine Klasse (also laden, speichern, löschen, ...)

    ne, is falsch, das is kein oop. in OOP gibt es keine funktionen. das was du beschrieben hast nennt man auch nicht kapselung. 👎


    hauptsache kluhg



  • qwerty` schrieb:

    aber gar nicht notwenig, in c++ sind funktionszeiger auch gute objekte, um als strategy benutzt werden zu können.

    Funktionen sind aber ungleich unflexibler als Objekte.

    was soll man da noch sagen?
    darf ich mal...

    template<typename F>
    void test(F f){
     f(17);
    }
    double sqr(double x){
     return x*x;
    }
    struct Sqr{
     static double operator(double x){
      return x*x;
     }
    };
    test(sqr);
    test(Srq());
    

    der test isses hier wurst, ob man ein objekt übergibt oder einen funktionszeiger. und das ist aktueller c++-stil.
    hier hat die operatorüberladung (sieghe anderer gelangweilter thread) zum teil für ein pragmatischeres objektverständnis gesorgt.



  • In diesem Fall verhalten sich Funktionspointer und Objekte genauso. Wenn ich mich aber recht erinnere, lassen sich Klassen und Funktionspointer in C++ schlecht mischen. Ausserdem braucht keine OOP-Sprache Funktionspointer, weil sie vollständig durch Objekte ersetzt werden können.

    Operatorüberladung ist ein anders Themengebiet.

    test(Srq());
    

    Ohne die Klasse Srq zu kennen würde ich hier annehmen das einfach nur ein Srq Objekt erzeugt wird. Das ist das gefährliche an Operatorüberladung.



  • DEvent schrieb:

    Ohne die Klasse Srq zu kennen würde ich hier annehmen das einfach nur ein Srq Objekt erzeugt wird. Das ist das gefährliche an Operatorüberladung.

    ähm. ohne oder mit solltest du annhemen, daß ein Sqr objekt erzeugt wird.
    keine akute gefahr.

    es geht ja eher um

    template<typename F> 
    double test(F f){ 
     double result=0;
     for(int i=0;i<10;++i)
      result+=f(i); 
     return result;
    }
    

    bei f(i) ist die operatorüberladung. für nur einmal-benutzen könnte (und sollte dringlichst) man sich den quark sparen.



  • Stimmt, ja, erst bei f() wird der Operator aufgerufen.
    Mein Argument bleibt aber, das wenn man Operatoren überläd, die Operatoren plötzlich ganz andere Wirkung haben könnten als erwartet.
    Ausserdem kann man z.B. den = Operator ganz anders interpretieren. Für die einen ist es eine einfache Adressen-Zuweisung, für andere ist es ein deep-copy-Operator.

    So eine ähnliche Diskussion hatten wir mal in dem Forum, da ging es um den + und += Operator bei String-Klassen.



  • DEvent schrieb:

    Stimmt, ja, erst bei f() wird der Operator aufgerufen.
    Mein Argument bleibt aber, das wenn man Operatoren überläd, die Operatoren plötzlich ganz andere Wirkung haben könnten als erwartet.
    Ausserdem kann man z.B. den = Operator ganz anders interpretieren. Für die einen ist es eine einfache Adressen-Zuweisung, für andere ist es ein deep-copy-Operator.

    ja, ohne zweifel muss man da bescheiden sein.
    mach klassen so, daß sie sich wie ints anfühlen!
    zum beispiel der op+ für strings ist bescheuert.
    denn "hallo"+"welt"==hallowelt"
    aber "welt"+"hallo"!="hallowelt"
    und gar "hallowelt"-"hallo" ist undefiniert.
    in den frühen zeiten von c++ wurden 2dimensionale arrays immer mit nem op()(int x,int y) ausgestattet. ja sogar listen mit nem op()(int position). das ist natürlich unfug.
    mein beipspiel mit dem op() ist da ok, man übergibt eine funktion, die was tun soll (oder ein objekt, das was tun soll) und ruft sagt der funktion/onjekt mit () dann "erfülle deinen zweck, mach, wozu du da bist, führe deinen code aus und berechne". im gegensatz ob reinen funktionen können objekte darüberhinaus noch andere sachen machen, aber im kontext der benutzenden test-funktion ist das objekt nur ein ding, das eine funktion ist. es wäre nicht toll, unterscheiden zu müssen und machmal sqrt(x) und macnhmal sqrt.calc(x) aufrufen zu müssen. ich will ja kein lexikon der wirren apis werden, sundern meinen geist aufsparen können, algorithmen zu bauen und uml-diagramme zu zeichnen. wenn die objekte einfach tun, was ich von ihnen erwarte, ist das schon ok.
    klar war in der frühen zeit von c++ (und die frühe zeit von c++ in diesem sinne wird in manchen unternehmen noch in 10 jahren aktuell sein) ein explorativer wildwuchs an der tagesordnung, der, wenn man die richtige datei angeguckt hat, in 5 minuten zu maximaler verwiirung geführt hat und schwach besaitete gemüter mussten mit dem krankenwagen weggefahren werden. das ist halt der preis einer freien sprache.



  • class Math {
       public:
          static double sqrt(double x) {
              return x*x;
          }
          static double sqr (double x, int t) {
              double y = x;
              for (int i = 0; i < t; i++) {
                 y *= x;
              }
              return y;
          }
          ...
    };
    

    Die Frage ist immer, wie man das Ganze zusammenfasst.
    Für sqrt allein ist eine Klasse unsinn. Wenn man nun aber noch andere mathematische Funktionen nutzt, dann ist das schon was anderes..



  • DocJunioR schrieb:

    class Math {
       public:
          static double sqrt(double x) {
              return x*x;
          }
          static double sqr (double x, int t) {
              double y = x;
              for (int i = 0; i < t; i++) {
                 y *= x;
              }
              return y;
          }
          ...
    };
    

    Die Frage ist immer, wie man das Ganze zusammenfasst.
    Für sqrt allein ist eine Klasse unsinn. Wenn man nun aber noch andere mathematische Funktionen nutzt, dann ist das schon was anderes..

    bei dir ist die wurzel als das quadrat. aha 😮



  • DocJunioR schrieb:

    class Math {
       public:
          static double sqrt(double x) {
              return x*x;
          }
    

    warum nicht in die klasse double rein?



  • DocJunioR schrieb:

    class Math {
       public:
          static double sqrt(double x) {
              return x*x;
          }
          static double sqr (double x, int t) {
              double y = x;
              for (int i = 0; i < t; i++) {
                 y *= x;
              }
              return y;
          }
          ...
    };
    

    Die Frage ist immer, wie man das Ganze zusammenfasst.
    Für sqrt allein ist eine Klasse unsinn. Wenn man nun aber noch andere mathematische Funktionen nutzt, dann ist das schon was anderes..

    Das ist keine Objekt Orientierte Programmierung. Ein Code ist ja nicht OO nur weil es das Wort class missbraucht äh enthält. Für so etwas gibt es in C++ übrigens Namespaces



  • rüdiger schrieb:

    DocJunioR schrieb:

    class Math {
       public:
          static double sqrt(double x) {
              return x*x;
          }
          static double sqr (double x, int t) {
              double y = x;
              for (int i = 0; i < t; i++) {
                 y *= x;
              }
              return y;
          }
          ...
    };
    

    Die Frage ist immer, wie man das Ganze zusammenfasst.
    Für sqrt allein ist eine Klasse unsinn. Wenn man nun aber noch andere mathematische Funktionen nutzt, dann ist das schon was anderes..

    Das ist keine Objekt Orientierte Programmierung. Ein Code ist ja nicht OO nur weil es das Wort class missbraucht äh enthält. Für so etwas gibt es in C++ übrigens Namespaces

    In eine 100% OOP-Sprache machma das aber so.
    C++ ist ja keine 100% OOP-Sprache, es vereint ja viele Programmierparadigmen in einer Sprache.



  • DEvent schrieb:

    In eine 100% OOP-Sprache machma das aber so.

    Aber eher notgedrungen, nicht weil es irgendwas mit OOP zu tun hat. Man packt hier "freie" Funktionen eben in eine Klasse, weil die Sprache nichts anderes unterstützt. Das ist einfach nur eine Emulation von freien Funktionen in einem Namespace. So wie man in C Klassen, virtuelle Methoden und Objekte durch Strukturen und Zeiger emulieren kann, muß man hier Funktionen durch Klassen emulieren. Mehr steckt doch nicht dahinter.

    Liest man sich die Designratschläge zu OO-Designs durch, so ist gerade diese Vorgehensweise "alles was noch übrig ist in eine Hilfsklasse stecken" eine ziemliche Todsünde.

    Offensichtlich zeigen solche Dinge eher, daß Sprachen, die ein Paradigma "zu 100%" erfüllen, schon zwangsläufig irgendwo unschöne Kompromisse enthalten müssen.



  • DEvent schrieb:

    rüdiger schrieb:

    [...]

    Das ist keine Objekt Orientierte Programmierung. Ein Code ist ja nicht OO nur weil es das Wort class missbraucht äh enthält. Für so etwas gibt es in C++ übrigens Namespaces

    In eine 100% OOP-Sprache machma das aber so.
    C++ ist ja keine 100% OOP-Sprache, es vereint ja viele Programmierparadigmen in einer Sprache.

    In einer 100% OOP-Sprache programmiert man nicht OO? Ich verstehe irgend wie nicht was du mir sagen willst.



  • "alles was noch übrig ist in eine Hilfsklasse stecken"

    Man fast alle Methoden die einer Kategorie angehören in eine Klasse, der Name dieser Klasse beschreibt die Kategorie.
    Ich verstehe nicht wo das Problem ist, man kann auch auf statische Methoden verzichten und sowas schreiben:
    [quote]

    class Mathe
    {
       private double nummer;
    
       public Mathe(double nummer)
       {
           this.nummer = nummer;
       }
    
       public double sqr(double potenz)
       {
           double y = nummer;
           for ( int i = 0; i < potenz; i++ ) y *= y;
           return y;
       }
    
       // weitere mathematische Funktionen
    }
    
    // verwendung:
    void main()
    {
        double x = 5.0;
        double y = new Mathe(x).sqr(5);
    }
    

    Man kann es natürlich auch ganz cool machen:

    class double
    {
        public double(/* irgendwas was ein fixnum ist*/ x)
        {
            /* x intern speichern */
        }
    
        public double sqr(double potenz);
    
       // weitere mathematische Funktionen
    }
    
    // verwendung:
    {
        double x = 5.0;
        double y = x.sqr(10);
    }
    

    Allerdings es das etwas übertrieben und so gibt es halt statische Methoden. Damit werden Klassen einfach nur auf eine Art package reduziert, weil man auf Instanzierung und Vererbung verzichtet. Wenn man die beiden Dinge nicht braucht, wozu das einem aufzwingen?
    Im Gegensatzt zu frei liegen Funktionen hat man aber den Vorteil das man diese Funktionen zusammengefasst hat. Sie sind nicht mehr kontexfrei.
    Zum Beispiel verhält sich die Funktion Betrag anders, wenn man sie bei Zahlen oder bei Vektoren verwendet wird.
    Bei einer Zahl ist Betrag einfach nur

    Zahl betrag(Zahl x) { return |x|; }
    

    Bei Vektor ist es

    Zahl betrag(Vektor x) { return wurzel(x.a0 * x.a1 * ... x.an); }
    

    So machtman die eine Funktion in die Klasse Mathe und die andere in die Klasse Vektor.
    Ein namespace ist dann dazu da, verschiede Klassen in ein Modul zusammen zufassen. Z.B. gehören die Klassen Mathe und Vektor in das Modul Mathematik. In das Modul System gehören die Klassen InputOutput, File, Peripherie...

    Liest man sich die Designratschläge zu OO-Designs durch, so ist gerade diese Vorgehensweise "alles was noch übrig ist in eine Hilfsklasse stecken" eine ziemliche Todsünde.

    Man hat ja normalerweise nichts übrig. Wie oben beschrieben steckt man jede "Funktion" der Kategorie nach in eine Klasse. Gut, Klassen die nur statische Methoden haben sind degenerierte Klassen. Aber das ist ja nur Faultheit des Programmierers (siehe Beispiel ganz oben).



  • @DEvent
    Eine Klasse ist keine Kategorie. Da hast du OOP falsch verstanden.

    Der richtige Ansatz für sqrt, wenn man es OO machen will, wäre, wie volkard schon gesagt hat

    class double {
    // ...
    public:
      double sqrt() const;
    };
    
    12.15.sqrt();
    double c=9.0;
    c.sqrt();
    

    So etwas können aber die wenigsten Programmiersprachen. Java und C# zwingen dich einfach dazu, das du Klassen missbrauchst.

    Das hat nichts mit Objekt Orientierter Programmierung zu tun. (Es heißt ja nicht Klassen Orientierte Programmierung. Klassen sind für OOP überhaupt nicht wichtig, sie sind nur ein Hilfsmittel einiger Programmiersprachen)



  • @ DEvent: Du hast einige sehr schoene Bilder auf deiner Homepage. Da kriege ich fast schon Heimweh. Trotzdem hast Du Unrecht was OOP angeht. 😉



  • So etwas können aber die wenigsten Programmiersprachen.

    Welche können das den ?

    @Apollon: danke 🙂



  • DEvent schrieb:

    Man fast alle Methoden die einer Kategorie angehören in eine Klasse, der Name dieser Klasse beschreibt die Kategorie.

    DIN 2342 definiert Begriff als eine "Denkeinheit, die aus einer Menge von Gegenständen unter Ermittlung der diesen Gegenständen gemeinsamen Eigenschaften mittels Abstraktion gebildet wird".
    und genau so ein ding brauchte die programmierung.

    eine klasse ist eine menge von objekten. klassen sind vereinfachte modelle von begriffen. statt aller begrifflichen beziehungen und gemeinsamer eigenschaften können klassen nur recht wenig ausdrücken.
    vor allem
    was hat so ein ding?
    was kann so ein ding?
    was ist so ein ding?

    was hat so ein ding? -> die attribute
    was kann so ein ding? -> die methoden
    was ist so ein ding? -> die basisklassen

    du definierst den begriff Math-Objekt und machst die existenz von Gegenständen dieses begriffs notwendig, um doubles zu manipulieren. so dinge heißen in der außenwelt taschenrechner.

    double y = new Taschenrechner().sqrt(25);//y=5
    

    *jeder*, der sowas eine zeit lang benutzen muss, schreibt in seine eigene klasse rein:

    double sqrt(double x){
       return new Taschenrechner().sqrt(x);
    }
    

    na, diese codevervielfachung wollen wir doch nicht provozieren, gell.

    die fans globaler funktionen wollen eher die fähigkeiten um doublemanipulationen zu frei verfügbarem wissen erklären, ein wissen, so allgemein, daß jedes objekt auf der welt es benutzen kann. kopfrechnen statt taschenrechner.
    jetzt braucht nicht mehr jeder, der mit doubles rechnen will, zum taschenrechner zu rennen. jetzt geht es genauso wie +, -, * und /. du wirst nicht bezweifeln, daß jeder schreiben kann double x; double y=x+5; die arithmetischen operatoren sind solche frei verfügbares wissen. und genauso verfügbar darf die kunst des radizierens sein.



  • DEvent schrieb:

    Welche können das den ?

    ich würd's zuerst probieren bei smalltalk, lisp und forth.



  • volkard schrieb:

    DEvent schrieb:

    Welche können das den ?

    ich würd's zuerst probieren bei smalltalk, lisp und forth.

    Mal sehen, wie es in Ruby aussieht:

    class Float
      def sqrt
        return Math.sqrt(self)
       end
    end
    
    print 9.8696044.sqrt
    

Anmelden zum Antworten