Java Language
Verkapselung
Suche…
Einführung
Stellen Sie sich vor, Sie hätten eine Klasse mit ziemlich wichtigen Variablen, und diese wurden (von anderen Programmierern aus ihrem Code) auf inakzeptable Werte gesetzt. Als Lösung lassen Sie in OOP zu, dass der Status eines Objekts (in seinen Variablen gespeichert) nur durch Methoden geändert wird. Das Ausblenden des Status eines Objekts und das Bereitstellen der gesamten Interaktion durch Objektmethoden wird als Data Encapsulation bezeichnet.
Bemerkungen
Es ist viel einfacher, eine Variable als private
zu markieren und bei Bedarf verfügbar zu machen, als eine bereits public
Variable auszublenden.
Es gibt eine Ausnahme, bei der die Kapselung möglicherweise nicht vorteilhaft ist: "dumme" Datenstrukturen (Klassen, deren einziger Zweck darin besteht, Variablen zu enthalten).
public class DumbData {
public String name;
public int timeStamp;
public int value;
}
In diesem Fall sind die Daten der Klasse die Schnittstelle der Klasse.
Beachten Sie, dass als final
gekennzeichnete Variablen als public
markiert werden können, ohne die Kapselung zu verletzen, da sie nach dem Setzen nicht mehr geändert werden können.
Kapselung zur Erhaltung von Invarianten
Eine Klasse besteht aus zwei Teilen: der Schnittstelle und der Implementierung.
Die Schnittstelle ist die offengelegte Funktionalität der Klasse. Seine öffentlichen Methoden und Variablen sind Teil der Schnittstelle.
Die Implementierung ist das interne Arbeiten einer Klasse. Andere Klassen sollten nicht über die Implementierung einer Klasse Bescheid wissen müssen.
Encapsulation bezieht sich auf die Praxis, die Implementierung einer Klasse vor allen Benutzern dieser Klasse zu verbergen. Dies erlaubt der Klasse, Annahmen über ihren internen Zustand zu treffen.
Nehmen Sie zum Beispiel diese Klasse, die einen Winkel darstellt:
public class Angle {
private double angleInDegrees;
private double angleInRadians;
public static Angle angleFromDegrees(double degrees){
Angle a = new Angle();
a.angleInDegrees = degrees;
a.angleInRadians = Math.PI*degrees/180;
return a;
}
public static Angle angleFromRadians(double radians){
Angle a = new Angle();
a.angleInRadians = radians;
a.angleInDegrees = radians*180/Math.PI;
return a;
}
public double getDegrees(){
return angleInDegrees;
}
public double getRadians(){
return angleInRadians;
}
public void setDegrees(double degrees){
this.angleInDegrees = degrees;
this.angleInRadians = Math.PI*degrees/180;
}
public void setRadians(double radians){
this.angleInRadians = radians;
this.angleInDegrees = radians*180/Math.PI;
}
private Angle(){}
}
Diese Klasse basiert auf einer Grundannahme (oder Invariante ): angleInDegrees und angleInRadians sind immer synchron . Wenn die Teilnehmer öffentlich sind, gibt es keine Garantie dafür, dass die beiden Darstellungen von Winkeln korreliert sind.
Kapselung zur Reduzierung der Kopplung
Mit der Kapselung können Sie interne Änderungen an einer Klasse vornehmen, ohne den Code zu beeinflussen, der die Klasse aufruft. Dies reduziert die Kopplung oder wie sehr eine bestimmte Klasse von der Implementierung einer anderen Klasse abhängt.
Ändern wir beispielsweise die Implementierung der Angle-Klasse aus dem vorherigen Beispiel:
public class Angle {
private double angleInDegrees;
public static Angle angleFromDegrees(double degrees){
Angle a = new Angle();
a.angleInDegrees = degrees;
return a;
}
public static Angle angleFromRadians(double radians){
Angle a = new Angle();
a.angleInDegrees = radians*180/Math.PI;
return a;
}
public double getDegrees(){
return angleInDegrees;
}
public double getRadians(){
return angleInDegrees*Math.PI / 180;
}
public void setDegrees(double degrees){
this.angleInDegrees = degrees;
}
public void setRadians(double radians){
this.angleInDegrees = radians*180/Math.PI;
}
private Angle(){}
}
Die Implementierung dieser Klasse wurde geändert, sodass nur eine Darstellung des Winkels gespeichert und der andere Winkel bei Bedarf berechnet wird.
Die Implementierung wurde jedoch geändert, die Schnittstelle jedoch nicht . Wenn eine aufrufende Klasse auf den Zugriff auf die angleInRadians-Methode angewiesen ist, muss sie geändert werden, um die neue Version von Angle
. Beim Aufruf von Klassen sollte die interne Repräsentation einer Klasse nicht berücksichtigt werden.