„Hallo Amigo! Ich möchte die heutige Vorlesung der Kapselung widmen. Du hast ja schon eine allgemeine Vorstellung davon, was das ist.“
Was sind also die Vorteile der Kapselung? Es gibt einige, aber ich möchte dir vier herausstellen, die meiner Meinung nach am wichtigsten sind:
1) Gültiger interner Zustand.
Programme haben häufig mehrere Klassen, die mit dem gleichen Objekt interagieren. Wenn sie gleichzeitig mit den internen Daten des Objekts interagieren, können sie die Datenintegrität des Objekts verletzen, was dazu führt, dass das Objekt nicht mehr korrekt funktioniert.
Das Objekt muss also alle Änderungen an seinen internen Daten verfolgen, oder besser noch: es muss diese Änderungen selbst vornehmen.
Wenn wir nicht wollen, dass eine Klassenvariable von anderen Klassen geändert wird, dann deklarieren wir sie als private. Das heißt, dass nur die Methoden dieser Klasse auf sie zugreifen können. Wenn wir wollen, dass Variablen für andere Klassen schreibgeschützt sind, dann fügen wir diesen Variablen einen public-Getter hinzu.
Zum Beispiel könnten wir wollen, dass jeder weiß, wie viele Elemente in unserer Collection vorhanden sind, aber niemand soll in der Lage sein, sie ohne unsere Erlaubnis zu ändern. In diesem Fall deklarieren wir die Variable private int count und die Methode public getCount().
Die richtige Kapselung garantiert, dass andere Klassen nicht direkt auf die internen Daten unserer Klasse zugreifen und diese folglich nicht verändern können, ohne dass wir ihre Aktionen kontrollieren können. Sie müssen Methoden über die Klasse aufrufen, welche die zu ändernden Variablen enthält.
Am besten gehst du davon aus, dass andere Programmierer deine Klassen immer so verwenden werden, wie es für sie am bequemsten ist, und nicht auf die Art und Weise, die für dich (oder deine Klasse) am sichersten wäre. Dies ist eine Quelle von Fehlern und du weißt jetzt, wie du sie verhindern kannst.
2) Überprüfung der Parameter.
Manchmal musst du die Parameter überprüfen, die an die Methoden deiner Klasse übergeben werden. Nehmen wir zum Beispiel an, wir haben eine Klasse, die eine „Person“ repräsentiert und du kannst ihr Geburtsdatum angeben. Wir sollten dann überprüfen, ob die eingegebenen Daten mit der Logik des Programms und der Logik der Klasse übereinstimmen. Es gibt zum Beispiel keinen 13. Monat, keinen 30. Februar usw.
„Warum sollte denn jemand als Geburtsdatum den 30. Februar angeben?“
„Naja, es könnte zum Beispiel ein Versehen bei der Dateneingabe sein.“
Außerdem kann ein Programm eine ganze Menge Bugs enthalten, bevor es irgendwann wie ein Uhrwerk funktuoniert. Zum Beispiel könnte so etwas passieren.
Ein Programmierer schreibt Code, der ermittelt, wer übermorgen Geburtstag hat. Sagen wir, heute ist der 3. März. Das Programm addiert 2 zum aktuellen Datum und findet jeden, der am 5. März geboren wurde. So weit, so gut.
Aber wenn der 30. März kommt, findet das Programm niemanden, da es keinen 32. März gibt. Programme enthalten viel weniger Bugs, wenn Methoden ihre Parameter überprüfen.“
„Ich erinnere mich daran, dass ich mir beim Thema ArrayList den Code angeschaut habe und es dort Überprüfungen in den get- und set-Methoden gab, um sicherzustellen, dass der Index-Parameter größer oder gleich Null und kleiner als die Länge des Arrays war. Der Code hätte eine Ausnahme ausgelöst, wenn das Array kein dem Index entsprechendes Element enthalten hätte.
„Ja, das ist eine klassische Eingabekontrolle.“
3) Weniger Bugs beim Ändern von Code innerhalb von Klassen.
Angenommen, wir haben eine wirklich nützliche Klasse als Teil eines großen Projekts geschrieben. Jeder findet sie so toll, dass andere Programmierer damit anfingen, sie an hunderten Stellen in ihrem eigenen Code zu verwenden.
Die Klasse erwies sich als so nützlich, dass du dich dazu entschieden hattest, sie zu verbessern. Aber wenn du eine der Methoden aus der Klasse entfernst, wird der Code von Dutzenden anderen Programmierern nicht mehr kompiliert. Sie müssten ihren Code dann schnell neu schreiben. Und je mehr man neu schreiben muss, desto mehr Möglichkeiten gibt es für Bugs. Wenn du so etwas regelmäßig tust, wird man dich hassen.
Aber wenn wir Methoden ändern, die als private markiert sind, wissen wir, dass diese Methoden nirgendwo von irgendeinem anderen Code aufgerufen werden. Wir können sie neu schreiben und die Anzahl und Art der Parameter ändern – der abhängige Code wird auch weiterhin funktionieren. Oder zumindest wird er sich noch kompilieren lassen.
4) Wir definieren, wie andere Objekte mit unserem Objekt interagieren werden.
Wir können die Aktionen, die auf unser Objekt angewendet werden können, beschränken. Beispielsweise könnten wir festlegen, dass nur eine Instanz einer Klasse erzeugt wird – auch wenn sie an mehreren Stellen im Projekt gleichzeitig erzeugt wird. Und das erreichen wir durch Kapselung.
Durch die Kapselung können wir zusätzliche Einschränkungen festlegen, die sich in zusätzliche Vorteile verwandeln können. So ist beispielsweise die Klasse String als ein unveränderliches Objekt implementiert. Eine Instanz der String-Klasse kann zwischen ihrer Erstellung und ihrer Zerstörung nicht verändert werden. Alle Methoden der Klasse String (remove, substring, ...) geben einen neuen String zurück und verändern das aufgerufene Objekt in keiner Weise.
„Heiliger Strohsack. So ist das also.“
„Kapselung ist faszinierend.“
„Du sagst es.“
GO TO FULL VERSION