Ein öffentliches Feld ist nicht schlechter als ein Getter/Setter-Paar, das nichts anderes tut, als das Feld zurückzugeben und es zuzuweisen. Erstens ist es klar, dass es (in den meisten Sprachen) keinen funktionalen Unterschied gibt. Jeder Unterschied muss in anderen Faktoren liegen, wie Wartbarkeit oder Lesbarkeit.
Ein oft genannter Vorteil von Getter/Setter-Paaren ist das nicht. Es wird behauptet, dass man die Implementierung ändern kann und die Clients nicht neu kompiliert werden müssen. Angeblich können Sie mit Settern später Funktionen wie die Validierung hinzufügen, ohne dass Ihre Kunden davon wissen müssen. Das Hinzufügen einer Validierung zu einem Setter ist jedoch eine Änderung seiner Vorbedingungen, einen Verstoß gegen den vorherigen Vertrag Sie lautete schlicht und einfach: "Sie können hier alles hineinlegen, und Sie können das Gleiche später aus dem Getter holen".
Da Sie nun den Vertrag gebrochen haben, sollten Sie jede Datei in der Codebasis ändern wollen und nicht vermeiden. Wenn Sie dies vermeiden, gehen Sie davon aus, dass der gesamte Code davon ausgeht, dass der Vertrag für diese Methoden anders ist.
Wenn das nicht der Vertrag sein sollte, dann erlaubte die Schnittstelle den Kunden, das Objekt in einen ungültigen Zustand zu versetzen. Das ist das genaue Gegenteil von Verkapselung Wenn dieses Feld nicht von Anfang an auf irgendetwas gesetzt werden konnte, warum war die Validierung dann nicht von Anfang an vorhanden?
Dasselbe Argument gilt für andere vermeintliche Vorteile dieser "Pass-Through"-Getter-Paare: Wenn Sie sich später entscheiden, den gesetzten Wert zu ändern, brechen Sie den Vertrag. Wenn Sie die Standardfunktionalität in einer abgeleiteten Klasse überschreiben, und zwar in einer Weise, die über ein paar harmlose Änderungen hinausgeht (z. B. Protokollierung oder anderes nicht beobachtbares Verhalten), brechen Sie den Vertrag der Basisklasse. Das ist eine Verletzung des Liskovschen Substituierbarkeitsprinzips, das als einer der Grundsätze von OO gilt.
Wenn eine Klasse diese dummen Getter und Setter für jedes Feld hat, dann ist es eine Klasse, die überhaupt keine Invarianten hat, kein Vertrag . Ist das wirklich objektorientiertes Design? Wenn die Klasse nur diese Getter und Setter hat, ist sie nur ein dummer Datenhalter, und dumme Datenhalter sollten wie dumme Datenhalter aussehen:
class Foo {
public:
int DaysLeft;
int ContestantNumber;
};
Das Hinzufügen von Getter/Setter-Paaren zu einer solchen Klasse bringt keinen Mehrwert. Andere Klassen sollten sinnvolle Operationen anbieten, nicht nur Operationen, die Felder bereits anbieten. Auf diese Weise können Sie nützliche Invarianten definieren und beibehalten.
Kunde : "Was kann ich mit einem Objekt dieser Klasse tun?"
Designer : "Sie können mehrere Variablen lesen und schreiben."
Kunde : "Oh... cool, denke ich?"
Es gibt Gründe, Getter und Setter zu verwenden, aber wenn es diese Gründe nicht gibt, ist es keine gute Sache, Getter/Setter-Paare im Namen falscher Kapselungsgötter zu bilden. Gültige Gründe für Getter oder Setter sind die Dinge, die oft als mögliche Änderungen genannt werden, die man später vornehmen kann, wie Validierung oder unterschiedliche interne Darstellungen. Oder vielleicht soll der Wert für Clients lesbar, aber nicht beschreibbar sein (z. B. die Größe eines Wörterbuchs), so dass ein einfacher Getter eine gute Wahl ist. Aber diese Gründe sollten vorhanden sein, wenn Sie die Wahl treffen, und nicht nur als eine potentielle Sache, die Sie vielleicht später wollen. Dies ist eine Instanz von YAGNI ( Du wirst es nicht brauchen ).
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 .