Klassen und Vererbung¶
Die Vererbung in Python ist einfacher und flexibler als die Vererbung in kompilierten Sprachen wie Java und C++, da die dynamische Natur von Python der Sprache nicht so viele Einschränkungen auferlegt.
Um zu sehen, wie Vererbung in Python verwendet wird, beginnen wir mit den
Klassen Square und Circle, die wir früher bereits besprochen haben, und
verallgemeinern sie.
Wenn wir diese Klassen nun in einem Zeichenprogramm verwenden wollen, müssen wir
definieren, wo auf der Zeichenfläche sich eine Instanz befindet soll. Wir können
dies tun, indem wir x- und y-Koordinaten für jede Instanz definieren:
1>>> class Square:
2... def __init__(self, length=1, x=0, y=0):
3... self.length = length
4... self.x = x
5... self.y = y
6...
7>>> class Circle:
8... def __init__(self, diameter=1, x=0, y=0):
9... self.diameter = diameter
10... self.x = x
11... self.y = y
12...
Dieser Ansatz funktioniert, führt aber zu einer Menge sich wiederholenden Codes,
wenn ihr die Anzahl der Form-Klassen erhöht, da ihr vermutlich wollt, dass jede
Form diese Positionsangabe hat. Dies ist eine Standardsituation für die
Verwendung von Vererbung in objektorientierten Sprachen. Anstatt die x- und
y-Variablen in jeder Form-Klasse zu definieren, könnt ihr sie in eine
allgemeine Form-Klasse abstrahieren und jede Klasse, die eine bestimmte Form
definiert, von dieser allgemeinen Klasse erben lassen. In Python sieht diese
Technik wie folgt aus:
1>>> class Form:
2... def __init__(self, x=0, y=0):
3... self.x = x
4... self.y = y
5...
6>>> class Square(Form):
7... def __init__(self, length=1, x=0, y=0):
8... super().__init__(x, y)
9... self.length = length
10...
11>>> class Circle(Form):
12... def __init__(self, diameter=1, x=0, y=0):
13... super().__init__(x, y)
14... self.diameter = diameter
15...
- Zeilen 6 und 11
SquareundCircleerben von derForm-Klasse.- Zeilen 8 und 13
rufen die
__init__-Methode derForm-Klasse auf.
Es gibt im Allgemeinen zwei Anforderungen bei der Verwendung einer geerbten
Klasse in Python, die ihr beide im Code der Klassen Circle und Square
sehen könnt:
Die erste Anforderung besteht darin, die Vererbungshierarchie zu definieren, was ihr tut, indem ihr die Klassen, von denen geerbt wird, in Klammern unmittelbar nach dem Namen der Klasse angebt, die mit dem Schlüsselwort
classdefiniert wird:CircleundSquareerben beide vonForm.Das zweite Element ist der explizite Aufruf der
__init__-Methode der geerbten Klasse. Dies erfolgt in Python nicht automatisch, sondern meist über diesuper-Funktion, genauer durch die Zeilensuper().__init__(x,y). Dieser Code ruft die Initialisierungsfunktion vonFormmit der zu initialisierenden Instanz und den entsprechenden Argumenten auf. Andernfalls würden für die Instanzen vonCircleundSquaredie Instanzvariablenxundynicht gesetzt.
Die Vererbung kommt auch dann zum Tragen, wenn ihr versucht, eine Methode zu
verwenden, die nicht in den Basisklassen, sondern in der Superklasse definiert
ist. Um diesen Effekt zu sehen, definiert eine weitere Methode in der Klasse
Form mit dem Namen move, die eine Form in den x- und
y-Koordinaten verschiebt. Die Definition für Form lautet nun:
1>>> class Form:
2... def __init__(self, x=0, y=0):
3... self.x = x
4... self.y = y
5... def move(self, delta_x, delta_y):
6... self.x = self.x + delta_x
7... self.y = self.y + delta_y
8...
Wenn ihr die Parameter delta_x und delta_y der Methode move in den
__init__-Methoden von Circle und Square übernehmt, könnt ihr z.B. folgende interaktive Sitzung ausführen:
>>> c = Circle(3)
>>> c.move(4, 5)
>>> c.x
4
>>> c.y
5
Die Klasse Circle im Beispiel hat nicht direkt eine move-Methode in sich
selbst definiert, aber da sie von einer Klasse erbt, die move implementiert,
können alle Instanzen von Circle die move-Methode verwenden. In
OOP-Begriffen könnte man sagen, dass alle Python-Methoden virtuell sind – d.h., wenn eine Methode in der aktuellen Klasse nicht existiert,
wird die Liste der Oberklassen nach der Methode durchsucht und die erste
gefundene verwendet.
Check¶
Schreibt den Code für eine
Triangle-Klasse um, sodass sie vonFormerbt.Wie würdet ihr den Code schreiben, um eine Methode
area()für die KlasseTrianglehinzuzufügen? Sollte die Methodearea()in die BasisklasseFormverschoben und anCircle,SquareundTrianglevererbt werden? Welche Probleme würde diese Änderung verursachen?