Die Verkapselung in Klassendefinitionen
-
19-08-2019 - |
Frage
Zum Beispiel, haben Sie Zugriffs- und Mutatoren innerhalb Ihrer Methode Definitionen verwenden oder einfach nur die Daten direkt zugreifen? Manchmal die ganze Zeit oder wenn in Rom?
Lösung
Versuchen Sie immer Accessoren zu verwenden, auch innerhalb der Klasse. Die einzige Zeit, die Sie Zustand wollen würden direkt zuzugreifen und nicht durch die öffentliche Schnittstelle ist, wenn Sie aus irgendeinem Grunde notwendig, um die Validierung oder andere Logik in der Accessormethode enthalten zu umgehen.
Nun, wenn man sich in der Situation, wo Sie tun müssen diese Logik umgehen, Sie sollten einen Schritt zurück und fragen Sie sich, ob diese Notwendigkeit, einen Fehler in Ihrem Design verrät.
Edit: Lesen Automatische vs Explicit Eigenschaften von Eric Lippert, in dem er in diesem Thema befasst und die Dinge sehr deutlich erklärt. Es handelt sich um C # speziell aber die OOP Theorie ist universell und solide.
Hier ist ein Auszug:
Wenn der Grund, die motiviert die ändern automatisch umgesetzt Eigenschaft explizit umgesetzt Eigenschaft war die Semantik zu ändern dann die Immobilie sollten Sie beurteilen, ob die gewünschte Semantik beim Zugriff auf das Eigentum von innerhalb der Klasse ist, die identisch oder verschieden von der gewünschten Semantik beim Zugriff auf das Eigentum von außerhalb der Klasse.
Wenn das Ergebnis dieser Untersuchung ist „Aus der Klasse, die gewünschte Semantik der Zugriff auf diese Eigenschaft unterscheiden sich von den gewünschten Semantik der Zugriff auf die Eigenschaft von außen“, dann bearbeiten hat Ein Fehler wurde eingeführt. Sie sollten das beheben Fehler. Wenn sie gleich sind, dann bearbeiten hat keine Fehler eingeführt; behalten die Umsetzung das gleiche.
Andere Tipps
Im Allgemeinen ziehe ich Accessoren / Mutatoren. Auf diese Weise kann ich die interne Implementierung einer Klasse ändern, während die Klasse funktioniert auf die gleiche Art und Weise an einen externen Benutzer (oder bereits existierenden Code, den ich will brechen nicht).
Die Accessoren sind so konzipiert, dass Sie Eigentum spezifische Logik hinzufügen. Wie
int Degrees
{
set
{
_degrees = value % 360;
}
}
Also, würden Sie wollen immer das Feld durch die Getter und Setter zuzugreifen und auf diese Weise können Sie immer sicher sein, dass der Wert wird nie mehr bekommen als 360.
Wenn, wie Andrew erwähnte, müssen Sie die Validierung überspringen, dann ist es durchaus möglich, dass es ein Fehler in der Konstruktion der Funktion ist, oder in der Gestaltung der Validierung.
Zugriffs- und Mutatoren sind so konzipiert, Konsistenz Ihrer Daten zu gewährleisten, so dass auch in Ihrer Klasse sollten Sie immer sicherstellen bemühen, dass es keine Möglichkeit, nicht validierten Daten in diesen Bereichen zu injizieren.
Bearbeiten
Sehen Sie diese Frage auch: OO-Design: Möchten Sie öffentliche Eigenschaften oder privat nutzen Felder intern?
Ich neige dazu, nicht die ‚Innereien‘ mit der Außenwelt zu teilen meinen Klassen und so für die Daten meiner internen Bedürfnisse (die privaten Sachen-Methode) neige dazu, nicht die gleiche Art von Sachen zu tun, die meine öffentliche Schnittstelle tut, in der Regel .
Es ist ziemlich ungewöhnlich, dass ich einen Accessor / Mutator schreiben, die eine private Methode nennen, aber ich vermute, ich in der Minderheit bin hier. Vielleicht I sollte mehr davon zu tun, aber ich neige nicht zu.
Wie auch immer, das ist meine [Patina bedeckt] zwei Cents.
Ich werde oft mit eigenem Auto Eigenschaften beginnt, dann Refactoring, wenn nötig. Ich werde mit einem Träger Feld auf eine Eigenschaft Refactoring, dann mit der „echten“ zu speichern, zum Beispiel Session oder für Viewstate einer ASP.NET-Anwendung des dahinter liegenden Feld ersetzen.
Von:
private int[] Property { get; set; }
private int[] _property;
private int[] Property
{
get { return _property; }
set { _property = value; }
}
private int[] _property;
private int[] Property
{
get
{
if (_property == null)
{
_property = new int[8];
}
return _property;
}
set { _property = value; }
}
private int[] Property
{
get
{
if (ViewState["PropertyKey"] == null)
{
ViewState["PropertyKey"] = new int[8];
}
return (int[]) ViewState["PropertyKey"];
}
set { ViewState["PropertyKey"] = value; }
}
Natürlich verwende ich ReSharper, so dass dies weniger Zeit zu tun, als darüber zu schreiben.