Getter und Setter



  • Eben, Getter und Setter sind eben alles was einen abstrakten Zustand eines Objektes erfragt oder verändert (am besten in einem für die Anwender zweckdienlichen weg). Ein Objekt ohne Zustand wäre irgendwie sinnlos.
    Es sollte eher ein spezieller Name für Methoden erfunden werden, die wirklich nur einen Datenmember verändern und auslesen und somit die Interna nach außen tragen. Dazu könnte man dann nämlich sagen, was hier vorher so allgemeingültig falsch behauptet wurde.



  • SeppJ schrieb:

    Tachyon schrieb:

    SeppJ schrieb:

    Alle von dir genannten Funktionen machen sehr viel mehr als einfach nur Getter/Setter für Interna der Klasse zu sein.

    Der Sinn von Gettern ist doch nicht die bloße Rückgabe eines Wertes, sondern gerade dass man das Abfragen/Setzen eines Wertes mit einer Aktion oder Konvertierung verbinden kann und das diese Dinge vor dem Client verborgen bleiben.

    Die hier diskutierten Getter und Setter aber gerade nicht! Das ist doch gerade das was dot aussagen will. Getter und Setter die einfach nur private member quasi-public machen sind oft unnötig und oft Zeichen schlechten Designs. Memberfunktionen die tatsächlich Arbeit verrichten und dabei private Member ändern (eventuell auch nur einen) sind hingegen Musterbeispiele für objektorientiertes Design.

    Wobei man hier anmerken muss, dass es sich auch so ergeben kann, dass dem so ist. Es ist kein Zeichen von schlechtem Design, nur weil die Getter und Setter trivial sind! Wenn ein gewisser Zustand nun eben sehr einfach in die übrige Modellierung des Objekts hineinpasst, warum sollte man sich da Sorgen machen und sich nicht einfach nur freuen?


  • Mod

    Artchi schrieb:

    SeppJ schrieb:

    Alle von dir genannten Funktionen (außer evtl. size und capacity) machen sehr viel mehr als einfach nur Getter/Setter für Interna des vectors zu sein.

    Und woher weißt du das? Doch nur weil du dich mit der Implementierung beschäftigt hast.

    Nein, habe ich nicht. Aber wie soll push_back ein setter sein? Da muss kopiert werden, Zeiger gesetzt werden, eventuelle Zähler erhöht werden, wenn's schlimm kommt sogar neu allokiert und alles kopiert werden. Das steht alles in den Anforderungen an vector. Es ist unmöglich das durch Änderung einer Variablen zu erreichen.

    Ebenso reserve und resize.

    operator[] muss mindestens ein bisschen Pointerarithmetik machen. at() zudem vergleiche durchführen.

    capacity und size könnten Getter sein, weil die Anforderung an diese ist, dass sie einfach einen Wert zurückgeben. Da kann man nicht wissen, ob dieser Wert nicht als privater Member gespeichert wird (da weiß ich aus der Implementierung, dass dies oft nicht so ist, aber das ist egal da ich ja nicht bestreite, dass die beiden keine getter wären).

    Aber gerade push_back, reserve und resize sind Gegenbeipiele zu Settern.


  • Mod

    Decimad schrieb:

    Eben, Getter und Setter sind eben alles was einen abstrakten Zustand eines Objektes erfragt oder verändert (am besten in einem für die Anwender zweckdienlichen weg). Ein Objekt ohne Zustand wäre irgendwie sinnlos.
    Es sollte eher ein spezieller Name für Methoden erfunden werden, die wirklich nur einen Datenmember verändern und auslesen und somit die Interna nach außen tragen. Dazu könnte man dann nämlich sagen, was hier vorher so allgemeingültig falsch behauptet wurde.

    Ja, ich glaube, dass dies das Problem in diesem Thread ist. Verwirrung durch Mängel in der menschlichen Sprache.



  • SeppJ,
    was ergibt es für einen Sinn solch eine Unterscheidung zu treffen?
    Sagen wir mal, wir haben eine Implementierung I von Klasse X und eine Implementierung J von Klasse X. Beide Implementierungen könnten die Daten komplett anders vorhalten. Während Methode Y bei Implementierung I dann ein Getter wäre, wäre sie in Implementierung J kein Getter mehr. Das würde bedeuten, dass es Implementierungsabhängig ist, ob Methode Y von Klasse X ein Getter ist oder nicht.



  • SeppJ schrieb:

    Die hier diskutierten Getter und Setter aber gerade nicht! Das ist doch gerade das was dot aussagen will. Getter und Setter die einfach nur private member quasi-public machen sind oft unnötig und oft Zeichen schlechten Designs. Memberfunktionen die tatsächlich Arbeit verrichten und dabei private Member ändern (eventuell auch nur einen) sind hingegen Musterbeispiele für objektorientiertes Design.

    Grundsätzlich führt man Getter/Setter doch gerade deshalb ein, weil man die Freiheit haben will, später irgendwelche Implementierungsdetails zu ändern, ohne das der Clientcode angepasst werden muss. Das es schlecht ist, prinzipiell jeden privaten Member über Setter/Getter public zu machen, ist wohl klar. Dann kann man sich auch gleich das private sparen.
    Mir erschließt sich jedoch nicht, wie Du aus der Frage des TO schließen willst, dass es um das prinzipielle publikmachen von Klasseninterna über Setter/Getter geht. Ich lese daraus eine Frage nach der Namenskonvention, und nicht mehr und nicht weniger.

    SeppJ schrieb:

    Aber gerade push_back, reserve und resize sind Gegenbeipiele zu Settern.

    Wieso insbesondere reserve und resize Gegenbeispiele für Setter sind, erschließt sich mir auch nicht. Wenn Du Setter als bloßes Mittel zum setzen einer Variable auf einen Wert siehst, dann hast Du den Grund dafür irgendwie nicht verstanden. Aus Client-Sicht tue ich nämlich genau das: Ich setze etwas auf einen gewünschten Wert.
    Es gibt da so ein tollen Beispiel für eine Klasse für komplexe Zahlen. Dort wird die Implementierung von Polarkoordinaten auf kartesische Koordinaten umgestellt, weil dem Autor aufgefallen ist, dass dies in seinem Kontext effizienter ist. Das Interface ändert sich dabei nicht. Auch nicht die Tatsache, dass es real und imag sowie für Betrag und Winkel Setter und Getter gibt.



  • So, und ich denke, worauf ihr abzielt ist eine ganz andere Aussage. Ein öffentlicher Getter/Setter gibt dem Benuter eine Garantie, dass ein solcher Zustand in irgendeiner Form von Objekten dieser Klasse verwaltet wird. Wenn man also unnötige Getter/Setter anbietet, dann muss man umso mehr Arbeit reinstecken, wenn man die Implementierung später ändert, um die Garantien, die die Schnittstelle gibt weiterhin zu erfüllen.



  • Decimad schrieb:

    So, und ich denke, worauf ihr abzielt ist eine ganz andere Aussage. Ein öffentlicher Getter/Setter gibt dem Benuter eine Garantie, dass ein solcher Zustand in irgendeiner Form von Objekten dieser Klasse verwaltet wird. Wenn man also unnötige Getter/Setter anbietet, dann muss man umso mehr Arbeit reinstecken, wenn man die Implementierung später ändert, um die Garantien, die die Schnittstelle gibt weiterhin zu erfüllen.

    Versteh ich nicht. Wenn auf die Attribute zugegriffen werden muss, hat man den Aufwand doch so oder so und wenn man mit anderen Methoden irgendwas erreichen kann, wird man die doch (vermutlich) sowieso verwenden.

    Ich würde mich jetzt aber auch nicht so auf die Begriffe Getter/Setter einschießen. Entspricht das irgend einem irgendwo definierten Terminus? Würde ich jetzt inuitiv verneinen.



  • Ich versuchte ja gerade in meiner Aussage davor darzulegen, dass eine Spezialisierung der Begriffe Getter/Setter über diejenige der Veränderung eines Astrakten Zustandes für den Benutzer gar keinen Sinn ergäbe, weil es von der Implementierung abhängt, ob die Begriffe dann zuträfen oder nicht.



  • Ich oute mich hiermit als Troll und danke euch dafür, dass ihr mitgespielt habt 🤡



  • Dann danke, dass du die Diskussion angeregt hast!


  • Mod

    @Tachyon: Was wäre dann der Unterschied zwischen Gettern/Settern und jeder beliebigen anderen Memberfunktion? Alle Memberfunktionen dienen letztlich dazu den Status des Objekts zu verändern oder zu erfahren.



  • SeppJ schrieb:

    @Tachyon: Was wäre dann der Unterschied zwischen Gettern/Settern und jeder beliebigen anderen Memberfunktion? Alle Memberfunktionen dienen letztlich dazu den Status des Objekts zu verändern oder zu erfahren.

    Eben, Namen sind Schall und Rauch.

    SeppJ schrieb:

    Nein, habe ich nicht. Aber wie soll push_back ein setter sein? Da muss kopiert werden, Zeiger gesetzt werden, eventuelle Zähler erhöht werden, wenn's schlimm kommt sogar neu allokiert und alles kopiert werden. Das steht alles in den Anforderungen an vector. Es ist unmöglich das durch Änderung einer Variablen zu erreichen.

    Ebenso reserve und resize.

    operator[] muss mindestens ein bisschen Pointerarithmetik machen. at() zudem vergleiche durchführen.

    Deine Argumentation mit dem push_back hört sich für mich so an, als ob du die Namen der Funktionen anhand der Implementierung wählst. Wenn ich meine Methodennamen danach auswählen würde, was die Methode alles am Ende des Tages abarbeiten muß, würden wir ganz schön miese Methodennamen haben.

    Mich interessiert als Client-Code überhaupt nicht, ob push_back irgendwas allokieren muß. Ich setze (set) mein Objekt an das Ende des Containers, und gut ist. Mich interessiert auch nicht, wie Size zustande kommt. Ich will die Größe wissen (get). Hauptsache sie liefert erstmal die richtige Größe, und keine falsche.

    Klar ist vector::set_X(T&) hässlicher weil weniger Aussagefähig als vector::push_back(T&) . Aber dann ist einfach nur der Name der Funktion in DEM Fall weniger verständlich, als push_back.


  • Mod

    Artchi schrieb:

    Deine Argumentation mit dem push_back hört sich für mich so an, als ob du die Namen der Funktionen anhand der Implementierung wählst.

    Wo liest du denn das heraus? Ich nenne Funktionen nach dem was sie tun. push_back ist ebenfalls ein guter Name, weil hinterher der Vector am Ende ein Element mehr hat. Wie es das macht, ist mir egal. Aus der Dokumentation von push_back weiß ich aber, dass es kein einfacher Setter in der Form ist, wie ihn Anfänger oftmals für alle privaten Member schreiben (also getX(){return X;} ) und genau um die häufige sinnlosigkeit dieser Art von Memberfunktion ging es in diesem Thread. Ob man das die Funktion nun getX() oder kdngekngiruegt() nennt ist ganz egal. Fakt ist, dass solche Arten von Funktionen sehr oft unnötig sind und die Objektabstraktion kaputtmachen. Wichtige Ausnahmen wurden genannt.
    Dies hat überhaupt gar nichts mit Funktionen zu tun, die den Zustand eines Objektes auf eine mit der Abstraktion konsistenten Art und Weise ändern oder nach außen kommunizieren. Dies ist doch gerade der Zweck der ganzen Objektorientierung. Um das abgedroschene Autobeispiel rauszuholen: Auch wenn meine Autoklasse einen Member namens Motor hat, so ist eine Funktion setMotor doch keine gute Funktionalität dieser Klasse, weil ein reales Auto welches die Klasse beschreiben soll, nicht einfach seinen Motor ändern kann.
    Eine Memberfunktion push_back ist daher eine sehr sinnvolle Funktion, denn die Abstraktion eines Vektors ist eine Liste an der man hinten was dranhängen und wegnehmen kann und bei der man die Elemente über eine Nummer eindeutig erreichen kann. Eine sehr schlechte Memberfunktion wäre ein Setter (im Sinne von setX(T newX){X=newX;} ) für irgendwelche Implementierungsdetails des Vektors, zum Beispiel für den Pointer auf das erste Element (falls es einen solchen gibt). Und gerade das ist es, worauf dot hinaus wollte und was sicherlich auch jeder einsieht, außer irgendwelche Besserwisser die dann einfach die Begriffe Getter und Setter (bewusst?) anders interpretieren, obwohl dies aus dem Zusammenhang offensichtlich sein sollte.


Anmelden zum Antworten