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



  • DEvent schrieb:

    Was ist wenn ich meine eigene Implementation der sqr-Funktion haben will.

    Dann überdeck ich die globale Version einfach in einem lokaleren Scope. Aber Funktionen ansich als Hilfsmittel für allgemeine Aufgaben sind ja kein Argument gegen Klassen, wie man z.B: auch mit static imports in Java sehen kann (auch wenn ich es deswegen nicht zwangsweise gutheiße).



  • Man hat schnell die Übersicht, man braucht nicht die Implementation der Menüs sehen, wenn man nicht will. Wenn man doch sehen will wie das Menu Datei aufgebaut ist, geht man flott in die Klasse MenuDatei rein.

    Also ich sehe nur Vorteile.

    Wie wäre es z.B: mit hochgradiger Redundanz als Nachteil? ..

    Überleg einfach mal durch was sich die 3 Klassen unterscheiden:

    • Text, bzw. Beschreibung
    • Listener, der die gewählte Aktion ausführt
    • eventuell Icon

    Langsam sollte es halt klingeln und offensichtlich werden, dass deine 3 Klassen in Wahrheit 3 Objekte sein sollten.



  • ich erinnere mich auch mit schrecken an
    class BubbleSort:public SortAlgorithm...



  • BTW: Wie macht man eigentlich folgendes, wenn man nicht OOP betreiben möchte...

    Man hat einen Algorithmus, der sehr lange braucht, deshalb will man den Fortschritt durch eine Art ProgressBar visualisieren.

    Im OOP-Fall würde ich mir da praktisch so ne Klasse basteln, wie volkard sie gerade mit dem Sortieren vorgeschlagen hat. Die Objekte dieser Klasse hätten dann halt einen inneren Zustand, der den aktuellen Fortschritt repräsentiert, den man von außen abfragen könnte. Wie macht man das ohne OOP? Da müsste man wohl mit Funktionen arbeiten, die Nebenwirkungen haben - wie auch die entsprechende Methode im OOP-Fall. Diese Nebenwirkungen wären aber nicht gerade lokal oder so... Wie baut man soetwas also vernünftig auf?



  • Gregor schrieb:

    Wie baut man soetwas also vernünftig auf?

    pushen statt pollen natürlich. dann bleibt der algo fast genausoschnell und der optimierer kann wegfetzen, wasimmer er will. beim pollen mußt du erlauben, daß der komplette zustand ausgewertet werden kann, auch schleifenvariablen, die eigenrlich in einem register liegen sollten. und alle lokalen variablen zu attributen zu machen ist auch durchaus unintuitiv.



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



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




  • //ungetestet
    //sollte aber ne flüssige anzeige ergeben
    void qsort(double a[],int min,int max,SortObserver obs){
       if(max-min<=1) return;
       obs.set(min);
       int pivot=(min+max)/2;
       partioniere;
       qsort(min,pivot,obs);
       qsort(pivot+1,max,obs);
    }
    


  • quote schrieb:

    ich erinnere mich auch mit schrecken an
    class BubbleSort:public SortAlgorithm...

    Das hat durchaus seine Berechtigung: Strategy Pattern

    volkard schrieb:

    pushen statt pollen natürlich.

    Prinzipiell funktioniert es dadurch natürlich ganz passabel, problematisch wird es aber durch diese "implizite" Definition. Jeder weitere Sortier-Algorithmus muss sich natürlich dementsprechend analog dazu nach außen verhalten ohne, dass es ihm vorgeschrieben werden kann. Bei einer SortingStrategy könnte man aber z.B: die zu sortierenden Daten kapseln und die Anzahl der Swaps mitzählen.



  • volkard schrieb:

    Gregor schrieb:

    Wie baut man soetwas also vernünftig auf?

    pushen statt pollen natürlich. dann bleibt der algo fast genausoschnell und der optimierer kann wegfetzen, wasimmer er will. beim pollen mußt du erlauben, daß der komplette zustand ausgewertet werden kann, auch schleifenvariablen, die eigenrlich in einem register liegen sollten. und alle lokalen variablen zu attributen zu machen ist auch durchaus unintuitiv.

    Wie das innerhalb der Klasse organisiert wird, ist ja mehr oder weniger nebensächlich. Da kann auch eine interne Variable für den Fortschritt drinstehen, die nur ab und zu aktualisiert wird.

    Wohin willst Du pushen? ...vor allem, wenn man dann noch davon ausgeht, dass vielleicht mehrere solcher Algorithmen parallel laufen usw. Wird das nicht ziemlich kompliziert, soetwas auf einer anderen Ebene zu regeln?

    Gib mal ein Beispiel. Geh mal von einem Algorithmus aus, der jedes Element eines int-Arrays mit 5 multiplizieren soll. In Java würde das wohl mit dr von mir vorgeschlagenen OOP-Variante so aussehen:

    public class Multiplier extends IntArrayProcessor
    {
       private final int factor;
       private int currentPosition;
       private int length;
    
       public Multiplier(int factor)
       {
          this.factor = factor;
          reset();
       }
    
       public void reset()
       {
          currentPosition = 0;
          length = 1;
       }
    
       public float getStatus()
       {
          return (float)currentPosition / (float)length;
       }
    
       public void process(int[] array)
       {
          length = array.length;
          for(int i = 0 ; i < array.length ; ++i)
          {
             array[i] *= factor;
             currentPosition = i;
          }
       }
    }
    

    ...und irgendein externer Mechanismus setzt das Ding dann in Gang und Frag bei Bedarf ab, wie weit es denn schon ist.



  • volkard schrieb:

    //ungetestet
    //sollte aber ne flüssige anzeige ergeben
    void qsort(double a[],int min,int max,SortObserver obs){
       if(max-min<=1) return;
       obs.set(min);
       int pivot=(min+max)/2;
       partioniere;
       qsort(min,pivot,obs);
       qsort(pivot+1,max,obs);
    }
    

    Ok, das wäre natürlich eine Möglichkeit. ...wobei der Observer offensichtlich auch aus der OOP-Richtung kommt. ...und die Fortschrittsanzeige wäre wohl auch nicht so ganz stabil. 😃 (Was aber wohl bei nem Quicksort eh problematisch wäre.)



  • qwerty` schrieb:

    quote schrieb:

    ich erinnere mich auch mit schrecken an
    class BubbleSort:public SortAlgorithm...

    Das hat durchaus seine Berechtigung: Strategy Pattern

    dann macht man zur not nen tiny wrapper drum. aber gar nicht notwenig, in c++ sind funktionszeiger auch gute objekte, um als strategy benutzt werden zu können.

    Jeder weitere Sortier-Algorithmus muss sich natürlich dementsprechend analog dazu nach außen verhalten ohne, dass es ihm vorgeschrieben werden kann.

    typprüfung gibts auch für funktionen.

    Bei einer SortingStrategy könnte man aber z.B: die zu sortierenden Daten kapseln und die Anzahl der Swaps mitzählen.

    das ist ja das einfachste. kannst auch jedem globalen bubblesort nen typ unterschieben, der seine swaps zählt. aber will man sortieralgos ausmessen, nimmt man besser die verbrauchte zeit.
    Gregors problem ist viel schwiereiger und praxisnah. man will nen fortschrittsbalken im sortierlauf. ich hab ne lösung angegeben.



  • Gregor schrieb:

    Ok, das wäre natürlich eine Möglichkeit. ...wobei der Observer offensichtlich auch aus der OOP-Richtung kommt.

    selbstverständlich. ich will ja alles, was sich nicht wehrt, in klassen stecken. und der observer whert sich nicht nur nicht, der bettelt darum.

    ...und die Fortschrittsanzeige wäre wohl auch nicht so ganz stabil. 😃 (Was aber wohl bei nem Quicksort eh problematisch wäre.)

    och, doch schon sehr. diese implemetierung dürfte fast ruckelfrei sein.
    aber klar, andere algos ruckeln in der anzeige mehr. bestes beispiel: bubblesort. er geht in der anzeige, den average-case annehmend, sehr langsam vorwärts, dabei immer schneller werdend. aber ah, oh, weh, nach dem dritten (echt lahmen) lauf hat er gemerkt, daß das array fertig sortiert ist (weil nur 3 zufügungen im vokabelbestand vergenommen wurden) und springt unvermittelt auf 100%. das problem ist aber unanhängig von klasse/funktion oder push/poll, dieser algo hat die weitsicht nicht.



  • Gregor schrieb:

    Gib mal ein Beispiel. Geh mal von einem Algorithmus aus, der jedes Element eines int-Arrays mit 5 multiplizieren soll.

    naja, der algo wie beim sort. und er pusht in nen observer rein.
    und jetzt kommt der trick:
    willste doch pollen, bist nicht du der observer, sondern du legst nen observer an, in den der algo pusht und du pollst den observer.
    begründung: sogar java vereckt prinzipiell mit

    private int currentPosition;
    

    und kann weniger optimieren, als mit lokalen nichtabfragbaren variablen.



  • 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. Wie wär es z.B mit einem Warnsystem für Hochwasser um ein eher konkretes Beispiel zu liefern?

    public class WaterLevelFilter implements Filter {
    
        private double criticalWaterLevel;
    
        public WaterLevelFilter(double criticalWaterLevel) {
           // ...
        }
    
        public boolean isCritical(Stream waterFlow) {
           return waterFlow.getWaterLevel() > criticalWaterLevel;
        }
    }
    

    Parameter wie die kritische Höhe des Wasserspiegels lassen sich mit Funktionen als Strategy recht schlecht implementieren.



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


Anmelden zum Antworten