Datenkapselung
🚧 | Diese Seite befindet sich in Bearbeitung | 🚧 |
🤓 | Diese Seite ist eine Bewertungsrichtlinie, die ab Blatt 2 annotiert und ab Blatt 3 abgezogen wird. | 🤓 |
Beschreibung
Es sollten nie komplexe veränderliche Objekte, Arrays oder Collections (z.B. ArrayList, HashMap) in direkter Form gesetzt oder ausgegeben werden, um einen Geheimnisverrat und eine Manipulation der Objekte zu verhindern. Betrachten wir hierzu ein kleines Beispiel:
// Innerhalb unserer Klasse
private int[] array;
public void setSomeArray(int[] array) {
this.array = array;
}
// Und an einer anderen Stelle
int[] somewhere = {0, 42, 1337, 4711};
setSomeArray(somewhere);
somewhere[2] = 666; // Manipulation durch böse Geister!
Nach dem Setzen des Arrays somewhere wird der Klasse in einer Ausgabe Methode etwaiges zu sehen sein: {0, 42, 1337. 4711}. In der letzten Zeile also insbesondere nach Festlegung des privaten und internen Arrays, verändern wir vermeintlich nur das außerhalb liegende Array somewhere und müssen leider feststellen durch unsere nach wie vor gültige Objektrefenzierung erhalten wir nun auch in der Klasse Ausgabe des Arrays array: {0, 666, 1337, 4711}. Ähnliche Beispiele können wir konstruieren nach Ausgabe eines internen Arrays.
Erstes Ziel sollte demnach sein, die Schnittstellen der Klasse so zu gestalten, dass überhaupt keine Arrays oder Listen nach außen gegeben werden müssen, bspw. durch anbieten von Methoden zum Hinzufügen oder entfernen einzelner Elemente anhand bestimmter Eigenschaften statt der Gesamtmenge.
Eine einfache Variante, dieses Problem dennoch zu umgehen, ist, eine echte Kopie der jeweiligen übergebenen oder auszugebenden Objekte zu erstellen. Im Falle von Arrays durch Nutzung von System.arraycopy(…) oder bei Collections und eigenen komplexen veränderliche Objekten durch eine "deep-copy", sprich: Ein neues Objekt vom gleichen Typ, mit gleichem Zustand erstellen und eintragen, das aber nicht das Original ist. Alternativ kann versucht werden, eigene komplexe veränderliche Objekte nicht veränderlich zu gestalten, bspw. Koordinaten oder anderweitige Tupel.
Negativbeispiel
public void setSomeArray(int[] array) {
this.array = array;
}
public int[] getSomeArray() {
return this.array;
}
Positivbeispiel
public void setSomeArray(int[] array) {
this.array = new int[array.length];
System.arraycopy(array, 0, this.array, 0, array.length);
}
public int[] getSomeArray() {
int[] copy = new int[this.array.length];
System.arraycopy(this.array, 0, copy, 0, copy.length);
return copy;
}