Sie sollten Getter und Setter verwenden, wenn:
- Sie haben es mit etwas zu tun, das begrifflich ein Attribut ist, aber:
- Ihre Sprache hat keine Eigenschaften (oder einen ähnlichen Mechanismus, wie die Variablenspuren von Tcl), oder
- Die Eigenschaftsunterstützung Ihrer Sprache ist für diesen Anwendungsfall nicht ausreichend, oder
- Die idiomatischen Konventionen Ihrer Sprache (oder manchmal Ihres Frameworks) fördern Getter oder Setter für diesen Anwendungsfall.
Es handelt sich also nur selten um eine allgemeine OO-Frage, sondern um eine sprachspezifische Frage mit unterschiedlichen Antworten für verschiedene Sprachen (und verschiedene Anwendungsfälle).
Vom Standpunkt der OO-Theorie aus sind Getter und Setter nutzlos. Die Schnittstelle Ihrer Klasse ist das, was sie tut, nicht was ihr Zustand ist. (Falls nicht, haben Sie die falsche Klasse geschrieben.) In sehr einfachen Fällen, in denen eine Klasse z.B. nur einen Punkt in rechtwinkligen Koordinaten darstellt,* sind die Attribute Teil der Schnittstelle; Getter und Setter verdecken dies nur. Aber in allen anderen als sehr einfachen Fällen sind weder die Attribute noch Getter und Setter Teil der Schnittstelle.
Mit anderen Worten: Wenn Sie glauben, dass die Verbraucher Ihrer Klasse nicht einmal wissen sollten, dass Sie eine spam
Attribut zu haben, geschweige denn, es willkürlich ändern zu können, und ihnen dann eine set_spam
Methode ist das Letzte, was Sie tun wollen.
* Selbst für diese einfache Klasse möchten Sie vielleicht nicht unbedingt die Einstellung der <code>x</code> y <code>y</code> Werte. Wenn dies wirklich eine Klasse ist, sollte sie dann nicht Methoden haben wie <code>translate</code> , <code>rotate</code> usw.? Wenn es nur eine Klasse ist, weil Ihre Sprache keine Records/Strukturen/benannte Tupel hat, dann ist das nicht wirklich eine Frage von OO
Aber niemand macht jemals einen allgemeinen OO-Entwurf. Sie entwerfen und implementieren in einer bestimmten Sprache. Und in einigen Sprachen sind Getter und Setter alles andere als nutzlos.
Wenn Ihre Sprache keine Eigenschaften hat, dann ist die einzige Möglichkeit, etwas darzustellen, das konzeptionell ein Attribut ist, aber tatsächlich berechnet oder validiert wird usw., die Verwendung von Gettern und Settern.
Selbst wenn Ihre Sprache über Eigenschaften verfügt, kann es Fälle geben, in denen diese unzureichend oder unangemessen sind. Wenn Sie zum Beispiel Unterklassen erlauben wollen, die Semantik eines Attributs zu kontrollieren, kann eine Unterklasse in Sprachen ohne dynamischen Zugriff ein Attribut nicht durch eine berechnete Eigenschaft ersetzen.
Was die Frage "Was ist, wenn ich meine Implementierung später ändern möchte?" betrifft (die sowohl in der Frage des Auftraggebers als auch in der akzeptierten Antwort mehrfach in unterschiedlicher Formulierung wiederholt wird): Wenn es sich wirklich um eine reine Implementierungsänderung handelt und Sie mit einem Attribut begonnen haben, können Sie es in eine Eigenschaft umwandeln, ohne die Schnittstelle zu verändern. Es sei denn natürlich, Ihre Sprache unterstützt das nicht. Es handelt sich also im Grunde um denselben Fall.
Außerdem ist es wichtig, die Idiome der Sprache (oder des Frameworks), die Sie verwenden, zu befolgen. Wenn Sie schönen Code im Ruby-Stil in C# schreiben, wird jeder erfahrene C#-Entwickler außer Ihnen Schwierigkeiten haben, ihn zu lesen, und das ist schlecht. Einige Sprachen haben eine stärkere Kultur um ihre Konventionen als andere - und es ist vielleicht kein Zufall, dass Java und Python, die am entgegengesetzten Ende des Spektrums liegen, was die Idiomatik von Gettern angeht, zufällig zwei der stärksten Kulturen haben.
Neben den menschlichen Lesern gibt es Bibliotheken und Werkzeuge, die von Ihnen erwarten, dass Sie die Konventionen einhalten, und Ihnen das Leben schwer machen, wenn Sie es nicht tun. Wenn Sie Interface Builder-Widgets mit etwas anderem als ObjC-Eigenschaften verknüpfen oder bestimmte Java-Mocking-Bibliotheken ohne Getter verwenden, machen Sie sich das Leben nur noch schwerer. Wenn die Werkzeuge für Sie wichtig sind, sollten Sie sie nicht bekämpfen.
8 Stimmen
@Dean J: D stackoverflow.com/search?q=getters+setters
10 Stimmen
Natürlich ist beides gleich schlecht, wenn das Objekt keine zu ändernde Eigenschaft benötigt. Ich würde lieber alles privat machen, und dann Getter hinzufügen, wenn es nützlich ist, und Setter, wenn es nötig ist.
31 Stimmen
Google "accessors are evil"
42 Stimmen
"Accessors sind böse", wenn Sie funktionalen Code oder unveränderliche Objekte schreiben. Wenn Sie zustandsbehaftete, veränderbare Objekte schreiben, dann sind sie ziemlich wichtig.
23 Stimmen
Erzählen, nicht fragen. pragprog.com/articles/tell-dont-ask
2 Stimmen
Mit Ausnahme von 6 und 8 würde ich es wagen zu sagen, dass keiner dieser Punkte in 99 % der Fälle zur Anwendung kommt. Dennoch würde ich gerne Java verwenden
String s = employee.name()
yemployee.name("oscar")
anstelle von getName() setName()1 Stimmen
@Oscar Reyes, ja, ich stimme zu, dass 6 und 8 meiner Erfahrung nach die beiden häufigsten sind. Das heißt, ich bevorzuge immer noch nicht mit der C#ish Syntax; mein alter Mann Gehirn wird verwirrt.
4 Stimmen
Ich bin überrascht, dass niemand über die Datensynchronisation spricht. Angenommen, Sie verwenden
public String foo;
es ist nicht fadensicher! Stattdessen können Sie definierenget
terset
ters mit Synchronisierungstechniken, um die Untreue von Daten zu vermeiden [d.h. ein anderer Thread, der das foo durcheinanderbringt]. Ich hielt es für erwähnenswert.3 Stimmen
@goldenparrot: Meistens ist die Synchronisierung einzelner Zugriffe auf ein Objekt viel zu ineffizient oder sogar anfällig für Synchronisierungsprobleme (wenn man mehrere Eigenschaften eines Objekts ändern muss sogleich ). IME, müssen Sie oft Operationen als Ganzes verpacken, die mehrere Zugriffe auf ein Objekt durchführen. Das kann nur durch Synchronisation auf der Seite der Benutzer eines Typs erreicht werden.
1 Stimmen
Fassen Sie Ihre Lieblingsstellen aus allen Antworten nicht in der Frage selbst zusammen. Dies ist eine Seite für Fragen und Antworten, kein Forum.
3 Stimmen
@ErikReppen was sollte ich lesen, um OOP überhaupt zu verstehen?
0 Stimmen
Es gibt auch das sehr wichtige Problem der gemeinsamen Nutzung von Code mit anderen, wenn Sie Objektfelder als Teile der externen Schnittstelle behandeln, die andere Leute nutzen können, dann könnte es unmöglich sein, das Feld in eine Funktion zu ändern, ohne Änderungen im Code anderer Leute zu zerstören.
0 Stimmen
@ErikReppen Danke für den Link, ich arbeite daran, zu verstehen, was OOP sein soll, aber es erweist sich als schwierig bei der Menge an Fehlinformationen, die im Umlauf sind. P.S. Ich finde auch, dass wikipedia eine der besten Quellen in vielen wissenschaftlichen Bereichen ist.
3 Stimmen
@TimoHuovinen es geht darum, nicht herausfinden zu müssen, welche von 500 Funktionen tatsächlich einen Wert ändert. Man macht einen Wert oder eine Reihe von Werten zu etwas, für das man verantwortlich ist, und nicht zu etwas, das man auf eine Param/Return-Achterbahn setzen kann. Vermeiden Sie Vanilla Getters/Setters und öffentliche Eigenschaften, und Sie werden oft feststellen, dass Sie innehalten und darüber nachdenken müssen, wie Sie Ihre Anwendung auf eine Art und Weise modellieren können, die in der Regel einfacher zu lesen, zu ändern, in großen Teilen wiederzuverwenden, zu debuggen ist und der Sie vertrauen können, ohne sie bis ins Mark zu testen. Java und C# haben OOP übertrieben und es dann aufgegeben, IMO.
1 Stimmen
In einem weiteren Artikel wird versucht, Leitlinien für die Verwendung von Gettern und Settern aufzustellen: Öffentliche oder private Mitgliedsvariablen? Das YAGNI-Prinzip leitet uns dazu an, erst dann Konstrukte hinzuzufügen, wenn wir wirklich wissen, dass wir sie brauchen werden.
0 Stimmen
Punkte 2, 3 (?), 4, 5 und 8: vorläufig ja. Die anderen: definitiv nein. Was spielt es für eine Rolle, ob Sie Python, C#, Ruby, Objective-C oder einen Esolang verwenden, wenn Ihr Code einfach, elegant und leicht wartbar/erweiterbar ist?
2 Stimmen
666 Upvotes scheinen kein Zufall zu sein
2 Stimmen
"Man kann leicht erkennen, dass Sie Python nicht benutzt haben" sollte eigentlich die Nr. 1 sein!
0 Stimmen
@Kaiserludi Könnten Sie erläutern, inwiefern das eine gute Sache ist?
0 Stimmen
@DeanJ Könnten Sie bitte die Nummer 10 erklären?
0 Stimmen
@Joshua: Das war nur ein Scherz, denn der Autor hat das eindeutig nicht ernst gemeint, als er es auf die Liste gesetzt hat.
2 Stimmen
11. T
1 Stimmen
Eine kürzlich gestellte Frage hat mich an einen weiteren Grund für Set-Methoden erinnert: die Möglichkeit, eine Änderung der Eigenschaft .