LU02b - Konzept des data hiding
Unter data hiding (Datenkapselung) versteht man den Zugriff auf die Attribute eines Objektes nur mittels Methoden und nie im Direktzugriff https://de.wikipedia.org/wiki/Datenkapselung_(Programmierung).
Im UML-Diagramm werden daher die Attribute mit dem Modifikator «private», hier ein - Zeichen versehen.
Abb. private-Modifikator in UML
Was bedeutet nun aber data hiding praktisch betrachtet?
Wir nehmen hier wieder unser Beispiel der Türe.
Gemäss UML-Diagramm sind alle Attribute private deklariert. Ein Zugriff in der Art
some_door = Door() some_door.door_is_open = True
ist somit nicht erlaubt.
Wäre dem nicht so, könnte z.B. auch im Zustand verriegelt die Türe geöffnet werden, was aber gar nicht geht.
Viel mehr wird in der Methode lock_the_door sichergestellt, dass eben die Bedingungen gemäss Zustandsdiagramm eingehalten werden.
def lock_the_door(self): """ Methode für das verriegeln der Türe. Das ist nur möglich, wenn die Türe nicht offen ist. Für das verriegeln ist aber das Türschloss zuständig. Es weiss wie das geht. """ if self._door_is_open == False: self._door_is_locked = self._the_door_lock.lock()
Der Benutzer der Klasse Door ist also vollständig von der Art der Implementation befreit und muss sich um keinerlei Zusicherungen kümmern.
Es genügt, wenn er die passenden Methode aufruft. Hier also
some_door.lock_the_door()
data hiding bei Python
Attribute
Attribute die im Klassendiagramm als private deklariert sind, müssen in Python im Konstruktor initialisiert werden.
Dies erfolgt durch folgende Schreibweise
self._attributname = initial_wert
Im Gegensatz zu anderen Programmiersprachen gibt es in Python keine echten private Attribute.
Mit der Schreibweise _attributname zeigen wir an, dass dieses Attribut nicht von ausserhalb der Klasse manipuliert werden soll.
Es wird aber nicht durch den Python-Interpreter verhindert, dass trotzdem auf solche Attribute zugegriffen wird.
Property und Setter
Durch den Einsatz von @property und @ATTRIBUT.setter können wir das Prinzip des Data Hidings unterstützen.
Als Beispiel betrachten wir das Attribut color der Klasse Door.
class Door: def __init__(self, ref2door_lock, base_color): self.color = base_color @property def color(self): """ getter-Methode für die Eigenschaft color :return: die Farbe des Objekts """ return self._color @color.setter def color(self, new_color): """ setter-Methode für die Eigenschaft color :param new_color: """ self._color = new_color if __name__ == '__main__': some_door = Door(None, 'blue') print(f'The color is {some_door.color}') some_door.color = 'red' print(f'The color is {some_door.color}')
Auf den ersten Blick scheint es, als würde das Programm in Zeile 24 direkt auf das Attribut color zugreifen.
Tatsächlich erkennt Python die Decorators @property und @color.setter und leitet die Zugriffe auf die entsprechenden Methoden um.
Wann verwende ich @property und @setter
Zunächst mal sollten alle Attribute als private betrachtet werden.
Soll ein fremdes Objekt Lese- oder Schreibzugriff auf ein Attribut erhalten, schreiben wir eine entsprechende Property (Lesen) und/oder Setter (Schreiben).
Entwerfen und Realisieren der Klasse
Beim Entwerfen einer Klasse stelle ich mir ein paar Fragen:
- Dürfen fremde Objekte den Wert dieses Attributs lesen? ⇒ Ich erstelle eine Property.
- Dürfen fremde Objekte den Wert dieses Attributs verändern? ⇒ Ich erstelle einen Setter.
Zugriff auf andere Objekte
Wenn ich in einem Programm auf ein Objekt zugreife, studiere ich zunächst mal seine Attribute und Methoden. Dabei achte ich auf einige Punkte:
- Der Bezeichner des Attributs beginnt mit einem
_⇒ Dies zeigt mir, dass ich nicht direkt auf das Attribut zugreifen soll.
Das ist beim Data Hiding der Normalfall. - Es gibt keine Property ⇒ Die Klasse möchte nicht, dass ich dieses Attribut lese.
- Es gibt keinen Setter ⇒ Ich soll das Attribut nicht direkt verändern.
Bei Python sind das einfach Empfehlungen. Wenn ich dies ignoriere, liegt das Risiko bei mir.

