Mit dem Ziel, für das Konzept der Kapselung die notwendigen Voraussetzungen bereit zu stellen, bietet Python die Kennzeichnung von Attributen mit einem oder zwei Unterstreichungsstrichen vor dem Attributanemn an.
Kennzeichnung der Sichtbarkeit | gilt für |
---|---|
self.__<name> | nur in der Klasse sichtbar [entspricht dem private bei Java] |
self._<name> | "per Konvention" geschützt |
self.<name> | auch von außen sichtbar [entspricht dem public bei Java] |
Schwierigkeiten im Zugriff ergeben sich bei den sinnvollerweise mit private geschützten Attributen eines Objektes, die in einer Oberklasse deklariert sind.
Der Konstruktor der erbenden Klasse kann auf eine privates Attribut der vererbenden Klasse nicht selbst zugreifen. Allerdings kann man das Problem dadurch lösen, dass der Konstruktor der erbenden Klasse explizit den Konstruktor der vererbenden Klasse mit super(...) aufruft und ihm die zu initialisierenden Parameter übergibt.
Der Aufruf von super(...) bei Python ist allerdings etwas ungewönlich [siehe Beispiel] und setzt voraus, dass die Oberklasse [die oberste der Hierarchie) ein "new styleclass" ist. Dazu muss sie von object [klein schreiben!] erben.
[Leider kann man bei Python den Schutz austricksen indem man beispielsweise mit stuhl._Stuhl__x=100 zugreift.]
Wenn Methoden der erbenden Klasse auf private Attribute der vererbenden Klasse lesend / schreibend zugreifen müssen, muss man eine entsprechende Get-Methode / Set-Methode bereitstellen, was möglicherweise zu einem Konflikt mit der gewollten Kapselung führen kann.
Bei dem Beispiel mit den einfachen Zaehlerklassen ohne Kapselung kann die Methode Zuruecksetzen() von Zaehler problemlos auf das Attribut self.stand von EinfacherZaehler zugreifen.
Ist der Stand gekapselt, muss die Methode Zuruecksetzen() in der Klasse EinfacherZaehler angesiedelt sein, so dass die Unterscheidung nicht mehr sinnvoll ist. Man sollte dann nur noch die eine Klasse Zaehler als Basisklasse verwenden.
Die Anwendung von super(...) ist wie oben schon angegeben bei Python ungewönlich. Das zeigt der Programmcode aus der Klasse ZyklischerZaehler zu dem veränderten Modell.
def Zaehle (self) : '''zaehlt den Zaehler jeweis um 1 weiter und setzt bei Erreichen der Zykluslaenge auf 0 zurueck''' super(ZyklischerZaehler, self).Zaehle() if self.GibStand()==self.__zyklusLaenge: self.Zuruecksetzen() # Kapselung!
Als Parameter von super(...) müssen die aufrufende (also nicht die vererbende) Klasse und das aufrufende Objekt übergeben werden.
© Claus Albowski