Vererbung bei Klassen in Python
Warum sollte eine Klasse etwas vererben? Gibt es auch digitales Sterben, könnte man sich fragen? Ja und Nein – aber was auf jeden Fall leidet, ist die Übersicht, wenn Klassen immer größer und größer und dadurch unübersichtlicher werden. Und daher ist wichtig, rechtzeitig eine Erbfolge aufzubauen, bevor die Übersichtlichkeit stirbt!
Was passiert bei der Vererbung von Klassen?
Die erbende Klasse übernimmt alle Eigenschaften und Methoden der beerbten Klasse!
Bleiben wir bei unserem Beispiel mit Katzen. Bisher hatte unsere Klasse Katzen folgenden Aufbau:
Klasse
Eigenschaften:
- Farbe
- Alter
- Rufname
Methoden:
- miauen
- schlafen
- fressen
- schmusen
Jetzt wollen wir den Überbegriff zur Katze: Es handelt sich um ein Tier und genauer um ein Säugetier (was man als Mensch auch manchmal beim Milchtritt der Katze direkt abbekommt).
Um das Beispiel besser ausbauen zu können, nehmen wir noch die Konkurrenz zur Katze dazu, also Hunde. Wir haben also für beide den Überbegriff Säugetier – unsere neue „Über“-Klasse, die es zu beerben gilt!

Und nun können die Eigenschaften der Katze in die Klasse Säugetier umgebaut werden. Die Oberklasse Säugetier bekommt nun Eigenschaften der Unterklasse Katze, damit auch etwas vererbt werden kann. In der Unterklasse Katze werden die übernommenen Eigenschaften entfernt und somit haben wir eine sehr aufgeräumte Klasse was den Code sehr gut lesbar macht.

Unser bisheriger Code:
class BauplanKatzenKlasse():
""" Klasse für das Erstellen von Katzen """
def __init__(self, rufname, farbe, alter):
self.rufname = rufname
self.farbe = farbe
self.alter = alter
self.schlafdauer = 0
katze_sammy = BauplanKatzenKlasse("Sammy", "orange", 3)
print(katze_sammy.farbe)
Jetzt erstellen wir unsere allgemeine Klasse „Tier“, die alle Eigenschaften der Katze erhält, was die Klasse der Katze bereinigt (doppelt ist unnötig):
class Tier():
""" Klasse für das Erstellen von Säugetieren """
def __init__(self, rufname, farbe, alter):
self.rufname = rufname
self.farbe = farbe
self.alter = alter
self.schlafdauer = 0
class BauplanKatzenKlasse():
""" Klasse für das Erstellen von Katzen """
katze_sammy = BauplanKatzenKlasse("Sammy", "orange", 3)
print(katze_sammy.farbe)
Nach dem Starten des Python-Programms erhalten wir allerdings eine Fehlermeldung, dass unsere Katzen-Klasse keinen Konstruktor hat, der das Argument übernehmen könnte.
Bisher gibt es auch noch keine Verbindung zwischen den beiden Klassen. Schaffen wir die Verbindung!
Vererbung aktivieren zwischen 2 Klassen
Um die Vererbung und die Erbreihenfolge festzulegen, muss nur die erbende Klasse im class
-Aufruf in Klammern die allgemeine Klasse notiert werden:
class BauplanKatzenKlasse(Tier):
Die __init__
-Methode wird weiterhin benötigt! Allerdings wird bei der erbenden Klasse innerhalb von __init__ die Eigenschaften über super()
aus der Eltern-Klasse (also die Klasse von der man erbt) „abgeholt“:
def __init__(self, rufname, farbe, alter):
super().__init__(rufname, farbe, alter)
Dieses erst einmal ominöse super()
steht für „superclass“, sprich Oberklasse. Wir stellen damit eine Verbindung zwischen der Eltern-Klasse (Klasse, von der Kind erbt) und Kind-Klasse her.
Und nun funktioniert das auch!
Unsere Katzen-Klasse ist schlanker geworden, wobei wir noch keinen Code gespart haben, da der bisherige Code in die neue Klasse „Tier“ gewandert ist. Hier der bisher erstellte Code komplett:
class Tier():
""" Klasse für das Erstellen von Säugetieren """
def __init__(self, rufname, farbe, alter):
self.rufname = rufname
self.farbe = farbe
self.alter = alter
self.schlafdauer = 0
class BauplanKatzenKlasse(Tier):
""" Klasse für das Erstellen von Katzen """
def __init__(self, rufname, farbe, alter):
""" Initalisieren über Eltern-Klasse """
super().__init__(rufname, farbe, alter)
katze_sammy = BauplanKatzenKlasse("Sammy", "orange", 3)
print(katze_sammy.farbe)
Legen wir nun eine weitere Kind-Klasse (also noch eine Klasse, die von der Eltern-Klasse erbt) an, sieht man die Ersparnisse deutlich. Und der Code ist übersichtlicher! Bauen wir eine Klasse Hund. Nachdem wir nun schon mit Klassen umgehen können und den sperrigen Namen „BauplanKatzenKlasse“ nicht wirklich schön ist, bekommt unsere Hunde-Klasse einen schöneren Namen, und zwar „Hund“. Zur Erinnerung: erkennbar ist die Klasse immer an der Schreibweise vom ersten Buchstaben in Großschreibung. Wir legen uns auch gleich ein neues Objekt „hund_bello“ zum Testen an, zum Testen, ob das alles funktioniert.
class Tier():
""" Klasse für das Erstellen von Säugetieren """
def __init__(self, rufname, farbe, alter):
self.rufname = rufname
self.farbe = farbe
self.alter = alter
self.schlafdauer = 0
class BauplanKatzenKlasse(Tier):
""" Klasse für das Erstellen von Katzen """
def __init__(self, rufname, farbe, alter):
""" Initalisieren über Eltern-Klasse """
super().__init__(rufname, farbe, alter)
class Hund(Tier):
""" Klasse für das Erstellen von Hunden """
def __init__(self, rufname, farbe, alter):
""" Initalisieren über Eltern-Klasse """
super().__init__(rufname, farbe, alter)
katze_sammy = BauplanKatzenKlasse("Sammy", "orange", 3)
print(katze_sammy.farbe)
hund_bello = Hund("Bello", "braun", 5)
print(hund_bello.farbe)
Methoden vererben in der OOP
Bisher haben wir uns nur die vererbten Eigenschaften angesehen. Genauso können wir die Methoden vererben. Als Erstes vererben wir unsere Methode „tut_schlafen()“. Schlaf benötigt jedes Tier und interessant ist bei unserer Methode, dass die Gesamtschlafdauer aufaddiert wird.
Unsere Klasse Tier wird nun über die Methode „tut_schlafen()“ erweitert.
class Tier():
""" Klasse für das Erstellen von Säugetieren """
def __init__(self, rufname, farbe, alter):
self.rufname = rufname
self.farbe = farbe
self.alter = alter
self.schlafdauer = 0
def tut_schlafen(self, dauer):
print(self.rufname, " schläft jetzt ", dauer , " Minuten ")
self.schlafdauer += dauer
print(self.rufname, " Schlafdauer insgesamt: ", self.schlafdauer, " Minuten ")
Weder bei unserer Katzen-Klasse noch bei der Hund-Klasse müssen wir irgendetwas machen. Beide erben automatisch alle Methoden der Eltern-Klasse „Tier“, die sofort zur Verfügung stehen. Das können wir auch gleich testen über:
hund_bello.tut_schlafen(4)
katze_sammy.tut_schlafen(5)
hund_bello.tut_schlafen(2)
Der Hund schläft öfters, dass man schön sieht, dass für jede Instanz (also Bello und Sammy getrennt voneinander) automatisch ein Schlafkonto geführt wird:
hund_bello.tut_schlafen(4)
katze_sammy.tut_schlafen(5)
hund_bello.tut_schlafen(2)
Unser Ergebnis ist:
Bello schläft jetzt 4 Minuten
Bello Schlafdauer insgesamt: 4 Minuten
Sammy schläft jetzt 5 Minuten
Sammy Schlafdauer insgesamt: 5 Minuten
Bello schläft jetzt 2 Minuten
Bello Schlafdauer insgesamt: 6 Minuten
Wir integrieren noch die Methode tut_reden()
in unsere Hauptklasse:
def tut_reden(self, anzahl = 1):
print(self.rufname, "sagt: ", anzahl * "miau ")
Unser kompletter Code:
class Tier():
""" Klasse für das Erstellen von Säugetieren """
def __init__(self, rufname, farbe, alter):
self.rufname = rufname
self.farbe = farbe
self.alter = alter
self.schlafdauer = 0
def tut_schlafen(self, dauer):
print(self.rufname, " schläft jetzt ", dauer , " Minuten ")
self.schlafdauer += dauer
print(self.rufname, " Schlafdauer insgesamt: ", self.schlafdauer, " Minuten ")
def tut_reden(self, anzahl = 1):
print(self.rufname, "sagt: ", anzahl * "miau ")
class BauplanKatzenKlasse(Tier):
""" Klasse für das Erstellen von Katzen """
def __init__(self, rufname, farbe, alter):
""" Initalisieren über Eltern-Klasse """
super().__init__(rufname, farbe, alter)
class Hund(Tier):
""" Klasse für das Erstellen von Hunden """
def __init__(self, rufname, farbe, alter):
""" Initalisieren über Eltern-Klasse """
super().__init__(rufname, farbe, alter)
katze_sammy = BauplanKatzenKlasse("Sammy", "orange", 3)
hund_bello = Hund("Bello", "braun", 5)
katze_sammy.tut_reden(1)
hund_bello.tut_reden(3)