Getter und Setter Frage



  • Uns wurde gesagt, man möge die Daten einer Klasse möglichst immer private machen, und den Zugriff darauf nur mit Get- und Set- Funktionen erlauben.
    Das sei wichtig wegen irgend einer Kapselung oder so etwas.
    Jetzt meine Frage:

    Erstmal Code:

    class Vektor{ // die erste Variante
     double x,y;
    public:
     Vektor():x(0),y(0){}
     Vektor(double xpos, double ypos):x(xpos),y(ypos){}
     void setX(double xpos){x=xpos;}
     double getX() {return x;}
     void setY(double ypos){y=ypos;}
     double getY(){return y;}
    };
    

    Wie man hier sieht muss ich hier einige Funktionen nur deshalb zusätzlich schreiben, weil x und y angeblich immer private sein müssen.

    Wenn ich also irgendwo dann einen

    int main(){
     Vektor X(2,3);
    

    erzeuge, und möchte im Laufe des Programms die x- oder y- Koordinate verändern oder abfragen, kann ich nur noch über die Funktionen zugreifen.
    Wozu soll der Unfug denn gut sein?

    eine zweite Variante mit public Daten:

    struct Vektor{ // die zweite Variante
     double x,y;
    };
    

    mir erscheint das zum einen nicht nur deutlich kompakter als die Variante 1 mit den private Elementen.
    Für die Zuweisung neuer Werte an eine double Variable gibt es ja bereits eine Funktion: den gewöhlichen = Operator. Wozu also eine zusätzliche Funktion schreiben, die dann ihrerseits erst wieder nichts besseres zu tun hat, als den Zuweisungsoperator für double Werte aufzurufen?
    Meiner Meinung nach macht es überhaupt keinen Sinn, die Daten private zu machen, wenn ich mit der Set-Funktion einen Wert verändern will, dauert das ja auch garantiert länger! Immerhin muss erst einmal zur Adresse der Get-Funktion gesprungen werden, bevor erst zur Adresse des Zuweisungsoperators für double Werte weiter gesprungen wird! Wären x und y nicht private, so könnten die Parameter sofort dem Operator= übergeben werden, und nicht über den Umweg der Set-Funktion. Das spart doch Zeit.

    Tut mir leid, vielleicht kann mir hier jemand erklären, warum man trotzdem die Daten unbedingt private machen soll und Get und Set Methoden verwenden muss.



  • Du hast vollkommen Recht, wenn man eine Klasse nur als Datenhalter benutzt, dann macht das keinen Sinn.

    Wenn du aber eine Klasse im objektorientierten Sinn verwendest, dann macht es Sinn die Attribute privat zu machen. Mach dich mit objektorientierter Programmierung vertraut und programmiere objektorientiert mit der Zeit wirst du verstehen was ich meine.



  • lolz schrieb:

    Du hast vollkommen Recht, wenn man eine Klasse nur als Datenhalter benutzt, dann macht das keinen Sinn.

    Wenn du aber eine Klasse im objektorientierten Sinn verwendest, dann macht es Sinn die Attribute privat zu machen. Mach dich mit objektorientierter Programmierung vertraut und programmiere objektorientiert mit der Zeit wirst du verstehen was ich meine.

    Also ist das Unsinn, dass man die Daten in jedem Fall und unbedingt private machen muss (das meint unser Professor nämlich!)? Danke, gut zu wissen. 🙂



  • Es kommt darauf an, was du vorhast.
    Wenn du "echte" Programme baust, dann willst du zum Beispiel relativ selten auf die einzelnen Komponenten eines Vektors zugreifen. Was du stattdessen willst sind Additionen, Skalar- und Vektormultiplikationen etc.
    Wenn du auf die Komponenten zugreifen willst, dann meistens über einen Index. Es wäre sehr unpraktisch, wenn du zB in einer Schleife über ein switch-case-Konstrukt die x- und y-Koordinate abrufen müsstest, wenn es auch viel allgemeiner über einen ganzzahligen Parameter ginge (operator[]).
    Dann sind die Daten ein Implementierungsdetail und gehen den Benutzer einen Dreck an.

    Die wenigen Ausnahmen sind bereits in der Standardbibliothek und Boost als std::pair und boost::tuple vorhanden.



  • IQ eines Rindes schrieb:

    .. und möchte im Laufe des Programms die x- oder y- Koordinate verändern oder abfragen, kann ich nur noch über die Funktionen zugreifen.
    Wozu soll der Unfug denn gut sein?

    Das ist genau der Punkt! Mal angenommen - nur angenommen (!) - Du hättest ein Programm mit 'perfektem' Design. Dann nenne mal alle Situationen bei denen Du an die X,Y-Koordinate ran willst. Und ich sage Dir dann warum Du das nicht brauchst. 🕶
    Ansonsten siehe auch hier.

    Gruß
    Werner



  • IQ eines Rindes schrieb:

    lolz schrieb:

    Du hast vollkommen Recht, wenn man eine Klasse nur als Datenhalter benutzt, dann macht das keinen Sinn.

    Wenn du aber eine Klasse im objektorientierten Sinn verwendest, dann macht es Sinn die Attribute privat zu machen. Mach dich mit objektorientierter Programmierung vertraut und programmiere objektorientiert mit der Zeit wirst du verstehen was ich meine.

    Also ist das Unsinn, dass man die Daten in jedem Fall und unbedingt private machen muss (das meint unser Professor nämlich!)? Danke, gut zu wissen. 🙂

    Kein Unsinn. privat ist die Regel, public die Ausnahme. Schonmal gefragt was sich die Entwickler von C++ wohl dabei gedacht haben warum eine Klasse default auf privat steht? Der Grundgedanke von Klassen im OOP ist, Daten in ihnen einzukapseln und das Objekt der Klasse nur über eine Funktionsschnittstelle zu bedienen. Der Zugriff auf interne Variablen soll nur indirekt möglich sein. Auf die Art ist die Implementierung der Klasse sozusagend "entkoppelt" und kann jederzeit verändert/ausgetauscht werden ohne das die übrigen Teile des Programms, die diese Klasse benutzen, umgeschrieben werden müssen.

    Es ist verständlich das man am Anfang den Sinn nicht versteht, jedoch ist es dumm zu glauben, nur weil man es nicht verstehe müsse es Unsinn sein...



  • Hallo

    Zu den bereits genannten Hinweisen noch dieser : Du gehst momentan nur von deinem Code nur für dich aus. Stell dir aber mal vor du arbeitest im Team, desen Code dann in eine allgemeine Library aufgenommen werden soll. Da gibt es dann Klassen, deren Attribute sich nur unter ganz bestimmten Bedingungen und mit ganz bestimmten Auswirkungen ändern dürfen. Außerdem gibt es Attribute die nach außen hin gar nicht zugreiffbar sein sollen. Sowas geht nur mit ordentlichen Gettern und Settern. Sonst würden dann andere Programmierer einfach die Attribute deiner Klassen ändern und die Fehler richtigerweise auf dich schieben. Das du also ordentlöiche Klasseninterfaces (also das Gesicht der Klasse nach außen hin) anbietest gehört zum gutem Stil.
    Nicht bei jeder Klasse mag eine komplette Kapselung nötig sein. Aber sicher ist sicher.

    bis bald
    akari



  • durch getter und setter sparst du dir z.b. eventuelle prüfungen auf nullpointer, weil die dinger im konstruktor gesetzt werden und immer gültige werte besitzen, die von aussen nicht geändert werden können.

    sollte das absolut keine rolle spielen, und deine getter und setter sind lediglich einzeilig (this->foo = foo / return foo), dann handelt es sich höchstwahrscheinlich nur um einen datenhalter, der seine member auf öffentlich machen kann. hierfür bietet sich in c++ dann struct statt class an, um den typ als datenstruktur kenntlich zu machen.



  • Genau diese Vektor-Klasse kann ein prima Beispiel sein, warum man Daten nicht public machen sollte.

    Zunächst einmal könnte ich einen Vektor statt mit x- und y-Koordinaten auch als Winkel und Radius speichern. Ich könnte dann genauso eine Getter und Setter für X- und Y-Koordinaten anbieten. Die wären nicht so performant. Dafür wäre die Methode zum ermitteln des Radiusses oder des Winkels performanter. Das wären 2 Implementierungsmöglchkeiten mit der gleichen Schnittstelle. Ich kann die Implementierung ändern ohne die Schnittstelle anpassen zu müssen.

    Ein anderes Argument ist gerade wieder beim Vektor passend: Mir fällt spontan kein Anwendungsfall ein, bei dem ich nur die X- oder nur die Y-Koordinate eines Vektors ändern muß. Eine Methode setX und eine Methode setY deuten auf einen Designfehler hin. Eine Methode "set(double x, double y)" wäre richtiger. Wenn ich eine Methode setX benötige, deutet das darauf hin, daß ich den Vektor nicht als Vektor-Objekt, sondern nur als Datenhalter verstehe. Die Setter-Methoden helfen damit, ein saubereres Design zu realisieren.

    Performance spielt hier aus 2 Gründen keine Rolle: erstens ist sauberes Design in der Regel wichtiger als das letzte Quentchen Performance und zweitens sind die gezeigte Getter- und Setter-Methoden kein bisschen schneller oder langsamer als der Direktzugriff, da die Methoden inline sind und von jedem C++-Compiler problemlos wegoptimiert werden.

    Ich würde die Aussage, man solle Daten möglichst immer private machen noch verschärfen: Mache Daten immer privat. Gut - Ausnahmen wie std::pair bestätigen die Regel, wie filmor bereits erwähnt hat.

    (Übrigens solltest Du die Getter const deklarieren)

    Tntnet



  • tntnet schrieb:

    Eine Methode setX und eine Methode setY deuten auf einen Designfehler hin. Eine Methode "set(double x, double y)" wäre richtiger.

    Noch richtiger waere

    v = Vector(x, y)
    

Anmelden zum Antworten