Zugriff auf die Attribute
Experimente mit Ampel-Objekten
Wir betrachten noch einmal eine Ampel mit den üblichen Ampelphasen.
Es gibt eine Vielzahl von Möglichkeiten, eine Klasse Ampel
zur Simulation einer
solchen Ampel zu konzipieren. Hier eine - neben den bisher betrachteten - weitere
Möglichkeit:
class Ampel(object):
def __init__(self):
self.zustand = 'rot'
self.lampeRot = None
self.lampeGelb = None
self.lampeGruen = None
self.aktualisiereLampen()
def getLampen(self):
return (self.lampeRot, self.lampeGelb, self.lampeGruen)
def schalten(self):
if self.zustand == 'rot':
self.zustand = 'rotgelb'
elif self.zustand == 'rotgelb':
self.zustand = 'gruen'
elif self.zustand == 'gruen':
self.zustand = 'gelb'
elif self.zustand == 'gelb':
self.zustand = 'rot'
self.aktualisiereLampen()
def aktualisiereLampen(self):
if self.zustand == 'rot':
self.lampeRot = True
self.lampeGelb = False
self.lampeGruen = False
elif self.zustand == 'rotgelb':
self.lampeRot = True
self.lampeGelb = True
self.lampeGruen = False
elif self.zustand == 'gruen':
self.lampeRot = False
self.lampeGelb = False
self.lampeGruen = True
elif self.zustand == 'gelb':
self.lampeRot = False
self.lampeGelb = True
self.lampeGruen = False
Ein Benutzer der Klasse Ampel
führt den folgenden Python-Dialog:
>>> a = Ampel()
>>> a.zustand
'rot'
>>> a.getLampen()
(True, False, False)
>>> a.schalten()
>>> a.zustand
'rotgelb'
>>> a.getLampen()
(True, True, False)
>>> a.zustand = 'gruen'
>>> a.zustand
'gruen'
>>> a.getLampen()
(True, True, False)
Aufgabe 1
Führe selbst diesen Dialog aus. Warum ist dieser Dialog nicht im Sinne des Ampelsystems? Woran liegt das?
Kapselung der Daten
Objekte nutzen Attribute, um die Daten, für die sie zuständig sind, zu verwalten. Ein leichtfertiger Zugriff auf die Attribute kann leicht zu unerwünschten Objektzuständen führen. Es ist daher eine gute Strategie, solche Zugriffe zu unterlassen oder sogar zu verbieten.
Wir setzen diese Strategie im Folgenden um, indem wir nicht mehr direkt auf Objektattribute
zugreifen. Es sollen also keine direkten Zugriffe der Form objekt.attribut
mehr erfolgen.
Ein Zugriff auf die Daten eines Objekts soll ab jetzt nur noch mit Hilfe geeigneter Methoden durchgeführt werden. Damit das möglich wird, erweitern wir zuerst die Klassendeklaration.
class Ampel(object):
def __init__(self):
self.zustand = 'rot'
self.lampeRot = None
self.lampeGelb = None
self.lampeGruen = None
self.aktualisiereLampen()
def setZustand(self, z):
self.zustand = z
self.aktualisiereLampen()
def getZustand(self):
return self.zustand
def getLampen(self):
return (self.lampeRot, self.lampeGelb, self.lampeGruen)
def schalten(self):
if self.zustand == 'rot':
self.zustand = 'rotgelb'
elif self.zustand == 'rotgelb':
self.zustand = 'gruen'
elif self.zustand == 'gruen':
self.zustand = 'gelb'
elif self.zustand == 'gelb':
self.zustand = 'rot'
self.aktualisiereLampen()
def aktualisiereLampen(self):
if self.zustand == 'rot':
self.lampeRot = True
self.lampeGelb = False
self.lampeGruen = False
elif self.zustand == 'rotgelb':
self.lampeRot = True
self.lampeGelb = True
self.lampeGruen = False
elif self.zustand == 'gruen':
self.lampeRot = False
self.lampeGelb = False
self.lampeGruen = True
elif self.zustand == 'gelb':
self.lampeRot = False
self.lampeGelb = True
self.lampeGruen = False
Mit den hinzugefügten Methoden lässt sich der oben gezeigte Vorgang jetzt so simulieren:
>>> a = Ampel()
>>> a.getZustand()
'rot'
>>> a.getLampen()
(True, False, False)
>>> a.schalten()
>>> a.getZustand()
'rotgelb'
>>> a.getLampen()
(True, True, False)
>>> a.setZustand('gruen')
>>> a.getZustand()
'gruen'
>>> a.getLampen()
(False, False, True)
Aufgabe 2
(a) Für welche Daten ist in diesem Beispiel das Ampel-Objekt zuständig?
(b) Überzeuge dich, dass im Shell-Mitschnitt kein direkter Zugriff auf die Daten des Ampel-Objekts erfolgt. Auf welche Weise kann man sich dennoch die Daten verschaffen?
(c) Warum ist es sinnvoll, dass Benutzer einer Klasse nur die Methoden der Klasse verwenden?