Lektionen des Moduls (2/4)
Vererbung
Vererbung (Inheritance) ermöglicht es dir, eine neue Klasse (die Subklasse) zu erstellen, die Attribute und Methoden einer bestehenden Klasse (der Basisklasse) erbt, und diese erweitern oder überschreiben (override) kann.
Basissyntax
class Animale:
def __init__(self, nome):
self.nome = nome
def saluta(self):
return f"{self.nome} fa un verso"
class Cane(Animale): # Cane ERBT von Animale
def saluta(self): # ÜBERSCHREIBEN (override) der Methode
return f"{self.nome} dice WOOF!"
a = Animale("X")
c = Cane("Fido")
a.saluta() # 'X fa un verso'
c.saluta() # 'Fido dice WOOF!'Cane erbt __init__ von Animale, ohne es neu schreiben zu müssen.
super(): Aufruf der Basismethode
Wenn du eine Basismethode erweitern (und nicht vollständig ersetzen) möchtest, verwende
super():
class Animale:
def __init__(self, nome):
self.nome = nome
class Cane(Animale):
def __init__(self, nome, razza):
super().__init__(nome) # delegiert an die Basisklasse
self.razza = razza
c = Cane("Fido", "Labrador")
c.nome # 'Fido'
c.razza # 'Labrador'isinstance: Typprüfung
isinstance(c, Cane) # True
isinstance(c, Animale) # True (auch die Basisklasse)
isinstance(c, str) # Falseisinstance(x, Basisklasse) erkennt auch alle Subklassen: Dies macht die Vererbung
nützlich für Polymorphismus.
animali = [Cane("Fido", "X"), Animale("Pippo")]
for a in animali:
print(a.saluta()) # jedes Objekt reagiert auf seine WeiseMRO (Method Resolution Order) — Übersicht
Bei Mehrfachvererbung entscheidet Python über die Reihenfolge der Methodensuche gemäß der MRO, berechnet mit dem C3-Algorithmus. In 95% der Fälle genügt es zu wissen:
- Suche zuerst in der Instanz,
- dann in ihrer Klasse,
- dann in den Basisklassen in Deklarationsreihenfolge.
Cane.__mro__
# (<class 'Cane'>, <class 'Animale'>, <class 'object'>)object ist die Wurzel jeder Klasse in Python 3.
Probiere es aus
Gegeben sei `class Vehicle: def __init__(self, brand): self.brand = brand`. Definiere `Car(Vehicle)` mit __init__(self, brand, model), das super().__init__ aufruft und self.model speichert. Erstelle `a = Car('Fiat', '500')` und evaluiere `(a.brand, a.model)`.
Hinweis anzeigen
super().__init__(brand) dann self.model = model.
Lösung nach 3 Versuchen verfügbar
Wiederholungsübung
Definiere `class Shape: def area(self): return 0` und `class Square(Shape)` mit __init__(self, side) und area(), das side * side zurückgibt. Erstelle `q = Square(5)` und evaluiere das Tupel `(q.area(), isinstance(q, Shape))`.
Hinweis anzeigen
self.side * self.side.
Lösung nach 3 Versuchen verfügbar
Zusätzliche Herausforderung
Erstelle eine Klasse `Square`, die von der Klasse `Rectangle` (unten definiert) erbt. Der Konstruktor von `Square` muss einen einzelnen Parameter `side` entgegennehmen und diesen an `super().__init__(side, side)` übergeben. Instanziiere ein Quadrat mit der Seitenlänge `6` in `sq` und evaluiere `sq.area()`.
Hinweis anzeigen
Deklariere class Square(Rectangle): und rufe super().__init__(side, side) im Konstruktor auf.
Lösung nach 3 Versuchen verfügbar