OOP mal wieder



  • Das ist wirklich schlecht.
    Nur alles was vorher ohne Klassen da stand jetzt in Klassen zu packen hat nichts mit OOP zu tun.
    http://en.wikipedia.org/wiki/State_pattern



  • Objektorientiert = Mit Objekten arbeiten

    Imho ist es vllt nicht der schönste Lösungsansatz, aber ich wollte, dass es nach aussenhin noch verständlich bleibt. Wenn du einen besseren Vorschlag hast lass hören, aber irgendwie seh ich hier nur kritik und keine alternativ Variante.



  • Und da bin ich wieder bei meinem ausgangsproblem...
    Alles was ohne Klassen ist in klassen schreiben finde ich in jedem tut...
    Nur leider/zum Glück/wie auch immer scheint das nicht so zu sein...

    Allerdings kann/hat hier niemand einen richtigen quellcode gepostet...
    Das würde vllt einiges Klarer machen...
    wäre nett wenn denn einer der es in richtigerem/besserem/oder wie auch immer oop kann mal so posten könnte...



  • Der grundlegende Code ist nicht wirklich geeignet um ihn zu "übersetzen".



  • --- schrieb:

    Der grundlegende Code ist nicht wirklich geeignet um ihn zu "übersetzen".

    Achja - Weil du das sagst ist das so?

    Man nimmt eine Klasse Lauflicht, den Konstruktor private und das switch setzt man als Factory Pattern um.

    Inwiefern das dann ein sinnvolles Programm ist, ist eine andere Frage.



  • @Entwickler
    Könntest du das mal machen?
    Mir würde das sehr helfen...
    MFG



  • Sqwan, zäun das pferd nicht von hinten auf.

    das schreiben einer klasse ist einfach und du sagtest, du kannst es.
    beschäftige dich jetzt mit dem programmierkonzept, also: was ist objektorientiertes design. und das unabhängig von einer konkreten sprache.

    viel spaß beim forschen.



  • Sqwan schrieb:

    @Entwickler
    Könntest du das mal machen?
    Mir würde das sehr helfen...
    MFG

    eigentlich hatte ich mir überlegt vlt. noch euin bsp. zu bringen, aber...



  • och, man kann das lauftlicht progrämmchen schon mal OO auffassen und gucken, was dabei rauskommt.

    es gibt ein licht. was ist das? ein gegenstand, der leuchten kann (nen buchstaben ausgibt). er selbst kann eigentlich nur leuchten, er kann sich wahrscheinlich nicht selbst anknipsen und schon gar nicht wird er den benutzer fragen, ob er leuchten soll.

    das licht ist also schlicht ein datencontainer, der über sich selbst weiss, wie er heisst (in welcher farbe er leuchtet) und das auch preisgeben kann.

    class Licht
    {
        private:
            string name;
        public:
            Licht(string name);
            string getName();
    };
    

    aber wie leuchtet so ein licht? muss wohl in einer fassung sitzen und diese fassung wird durch irgendwas kontrolliert. da es sich um ein lauflicht handeln soll und je nach eingabe ein anderes licht aktiviert wird, handelt es sich dabei höchst wahrscheinlich um ein einzelnes gerät, welches alle lichter steuert und dazu auch über das vorhanden sein der lichter bescheid weiss. nennen wir ihn mal lichtkasten. um diesen lichtkasten "füllen" zu und mit ihm interagieren zu können, spendieren wir ihm methoden, um lichter hinzuzufügen, deren anzahl abzufragen und ein licht gezielt umzuschalten.

    class Lichtkasten
    {
        private:
            vector<Licht> lichter;
        public:
            void addLicht(Licht licht);
            int lichtCount();
            void toggleLicht(int index);
    };
    

    für "benutzerfreundlichkeit" wäre es womöglich noch schön, an das jeweilige licht direkt heranzukommen. oder die lichter mittels namen ansprechen zu können. das kommt je auf die verwendung an. dieser lichtkasten hier kann anonym durch seine lichter schalten.

    nun gibt es lichter und einen lichtkasten, der diese kontrollieren kann. super, wie soll er nun angesprochen werden? automatisch oder per benutzereingaben? laut beispielprogrämmchen mittels benutzereingaben. also können wir uns eine klasse basteln, die benutzereingaben handhabt und dadurch den lichtkasten steuert.

    class BenutzerInterface
    {
        public:
            void setControls(Lichtkasten kasten);
            bool getUserInput();
    };
    

    getUserInput() ist hier so konzipiert, dass es solange true liefert, wie der benutzer gültige eingaben tätigt.

    wie man das ganze nun zusammenklebt bleibt jedem selbst überlassen. c++ typisch kann man für so ein kleines programm alles in der main() zusammenkleben und dann ausführen.

    int main()
    {
        Lichtkasten lk;
        lk.addLicht(Licht("A"));
        lk.addLicht(Licht("B"));
        lk.addLicht(Licht("C"));
        BenutzerInterface ic;
        ic.setControls(lk);
        while(ic.getUserInput());
    }
    

    "wahre" OO jünger streiten sich übrigens darüber, ob in der main "soviel" code stehen darf. oder ob das nicht schon wieder nicht OO ist. aber als grundsätzliches beispiel für einen OO ansatz fand ich das nu gar nich so schlecht 😃



  • Ok... das bsp finde ich sehr sehr gut...
    Allerdings verstehe ich nicht was dieses vector macht...
    vllt kann das noch mal kurz einer erklären...
    Google sacht mir da so nen zeuch mit 3 diminensionalem raum im koordinatensystem



  • Sqwan schrieb:

    Google sacht mir da so nen zeuch mit 3 diminensionalem raum im koordinatensystem

    Das ist ein Vektor im mathematischen Sinne, hier ist es einfach ein Array aus der Std-Bibliothek 🤡



  • Also ich habe mal was versucht...

    sieht so aus...

    #include <iostream>
    
    using namespace std;
    
    class Rechnen
    {
    
    private:
    	float zahl1;
    	float zahl2;
    	char operators;
    	float ergebnis;
    
    public:
    
    	//So wie ich es verstanden habe der Konstruktor
    	void Calculator()
    	{
    		zahl1 = 0;
    		zahl2 = 0;
    		operators = 'z';
    		ergebnis = 0;
    	}
    
    	//Methode
    	void newZahl1(float zahl)
    	{
    		zahl1 = zahl;
    	}
    
    	//Methode
    	void newZahl2(float zahl)
    	{
    		zahl2 = zahl;
    	}
    
    	//Methode
    	void setOperator(char zeichen)
    	{
    		operators = zeichen;
    	}
    
    	//Methode
    	void calculate()
    	{
    		switch(operators)
    		{
    			case '+': ergebnis = zahl1 + zahl2; break;
    			case '-': ergebnis = zahl1 - zahl2; break;
    			case '*': ergebnis = zahl1 * zahl2; break;
    			case '/': ergebnis = zahl1 / zahl2; break;
    			default:  cout<<"Falsche Eingabe!"<<endl; break;
    		}
    	}
    
    	//Methode
    	void ShowResult()
    	{
    		cout<<zahl1<<" "<<operators<<" "<<zahl2 <<" = "<<ergebnis;
    	}
    };
    
    void main()
    {
       Rechnen rechenmaschine;
       rechenmaschine.Calculator();
       rechenmaschine.newZahl1(10);
       rechenmaschine.newZahl2(20);
       rechenmaschine.setOperator('+');
       rechenmaschine.calculate();
       rechenmaschine.ShowResult();
    }
    

    kommt mir sehr sinnlos rüber und irgendwie falsch.
    Denn vorher hatte ich weniger quellcode.
    Und leichter sah es vorher auch aus.
    Nur geordneter is es glaube ich ein wenig



  • //So wie ich es verstanden habe der Konstruktor
        void Calculator()
    

    ein konstruktor heisst stets genau wie die klasse und hat keinen rückgabetyp. void IST ein rückgabetyp, der keinen wert liefert (umgangssprachlich, void zeiger können sehr wohl wieder auf einen "wert" zeigen).

    in deinem beispiel müsste der konstruktor also wie folgt lauten

    class Rechnen
    {
     ...
     Rechnen() // konstruktor
     {
     ...
     }
    };
    

    was OO ausmacht ist, wie hier bereits erwähnt, grundsätzlich erstmal ein anderes verständnis des problems. man versucht in dem problem auszumachen, wo sich objekte befinden. ein gutes beispiel ist vielleicht ein apfelbaum.

    ein apfelbaum hat äste, blätter und früchte.

    zu den ästen gehört auch der stamm, die wurzeln und das, was man typischerweise als äste bezeichnet. die blätter und früchte hängen immer an den ästen.

    je nach gewünschter granularität kann man hier nun aufteilen. vielleicht benötigt man die unterteilung in äste, stamm und zweige gar nicht und nennt das grundkonzept einfach nur "baum". dieser baum hat dinge, die an ihm dranhängen. nennen wir es "zeugs". "baum" ist also ein container, der "zeugs" beinhaltet.

    class Baum
    {
     vector<Zeug*> zeugs;
    
     public:
      addZeugs(Zeug* zeug){ zeugs.push_back(zeug); }
    };
    

    dieses zeugs kann nun entweder ein blatt oder ein apfel sein, womit man schon beim thema vererbung wäre. blätter und äpfel sind beide vom typ "zeugs", aber da man beide anders behandeln will, schafft man sich zwei verschiedene klassen dafür.

    class Zeug
    {
     string name;
    };
    
    class Apfel : public Zeugs
    {
     Apfel(){ name = "Apfel"; }
    };
    
    class Blatt : public Zeugs
    {
     Blatt(){ name = "Blatt"; }
    };
    


  • Ah ja soviele Tutorials hast du durchgearbeitet und noch nicht mal nen Konstruktor kriegst du hin. Ich glaube du hast dir nicht viel Mühe gegeben.



  • gib mir nen link zu nem Tutorial wo das steht...
    In denen die ich gelsen habe, steht das der konstruktor die variablen auf die grundwerte setzt...
    Das er den selben namen haben muss steht das nicht...
    Wo ihr es sagt fällts allerdings auf...
    und auch in meinem c++ buch sind zwar alle konstruktor mit dem namen der klasse identisch... aber das das so sein muss steht da nicht...

    Vllt bin ich auch einfach zu blöde mir ordnetliche OOP tuts zu suchen...

    und wie ich das hier sehe habe ich es immer ziemlich falsch verstanden...
    das letzt was ich gelesen(eher überflogen) habe, stand drinne das eine prog häufig mehrere aufgaben hat...

    Jede aufgabe bekommt ein Objekt..
    Und im objekt teilt man dann die probleme in die methoden...

    So wie ich es jetzt verstanden habe, teilt man die probleme einer aufgabe in objekte auf... und die probleme teilt man dann in die methoden...
    Oder sehe ich das falsch...

    EDIT:
    habe grade eine tut gefunden da steht drinne das ein konstruktor in Java den selben namen haben muss...



  • Sqwan schrieb:

    gib mir nen link zu nem Tutorial wo das steht...
    In denen die ich gelsen habe, steht das der konstruktor die variablen auf die grundwerte setzt...
    Das er den selben namen haben muss steht das nicht...
    Wo ihr es sagt fällts allerdings auf...
    und auch in meinem c++ buch sind zwar alle konstruktor mit dem namen der klasse identisch... aber das das so sein muss steht da nicht...

    Zitat aus C++, die Programmiersprache, Seite 240 (KOnstruktoren): "Ein Konstruktor ist dadurch gekennzeichnet, daß er denselben Namen hat wie die zugehörige Klasse".

    Manchmal hilft es wirklich die Standartwerke zu besitzen... Und sie auch zu lesen 😉



  • Wi wir schonmal dabei sind: Ein Destruktor hat auch denselben Namen wie die Klasse, nur mit ~ davor. Und du brauchst weder Konstruktor noch Destruktor extra aufzurufen 😉

    class Cl
    {
        public:
            Cl()
            {
                cout << "Konstruktor" << endl;
            }
    
            ~Cl()
            {
                cout << "Destruktor" << endl;
            }
    };
    
    void IrgendNeFunktion()
    {
        Cl BlaVariable; //--> Hier wird der Konstruktor aufgerufen
        ...
        //--> Und hier der Destruktor, genau vor der Klammer-Zu
    }
    
    void Func2()
    {
        Cl* pVar;
        ...
        Cl = new Cl; // Konstruktor
        ...
        delete Cl;  // Destruktor
        ...
    }
    


  • http://www.cpp-tutor.de

    Wenn du das durchgearbeitet hast kannst du wiederkommen.



  • Also ich finde thordks Erklaerungen sehr hilfreich. Schoen seine Analyse des Problems beschrieben und wie man das dann eben umbaut. Sehr nett, danke dir!

    Und ich glaube wenn man

    So wie ich es jetzt verstanden habe, teilt man die probleme einer aufgabe in objekte auf... und die probleme teilt man dann in die methoden...
    Oder sehe ich das falsch...

    noch bisschen umformulieren wuerde kaeme doch was ganz verstaendliches dabei raus, oder nicht?



  • Badestrand! Soweit fast richtig.

    Hier wird ebend gerade nicht der Ctor aufgerufen:

    Cl = new Cl; // Konstruktor
    

    Hier schon:

    Cl = new Cl(); // Konstruktor
    

Anmelden zum Antworten