Ableitung und Vererbung – ein Supertoaster

Zuletzt noch eine ganz wichtige Eigenschaft von Klassen und Objektdefinitionen. Vielleicht findest du den Toaster ganz nett und erstellst dir in einem Programm mehrere Toaster-Objekte, zum Beispiel toasty, toasty2, toastmaster usw. … Als Nächstes willst du aber einen zusätzlichen Toaster erschaffen, der noch mehr kann. Einen, bei dem man die Temperatur einstellen kann und der einen Alarm ausgibt, wenn er zu heiß wird. Alle anderen Eigenschaften, die der normale Toaster hat, soll er ebenfalls haben.

Klar – man könnte jetzt einfach eine neue Objektklasse definieren, die mehr Variablen und Funktionen enthält als die bisherige Klasse Toaster. Aber warum das Rad neu erfinden, wenn schon die Grundeigenschaften einmal da sind? Was wir eigentlich brauchen, ist eine Erweiterung der Klasse Toaster. Das geht so:

class SuperToaster(Toaster):

Wieder die Definition einer Klasse, diesmal mit dem Namen SuperToaster, aber in Klammern wird bei der Klassendefinition eine bereits vorhandene Klasse angegeben, nämlich Toaster.

Das bedeutet, dass diese neue Klasse automatisch alle Variablen und Methoden der Klasse »Toaster« übernimmt. Man sagt auch, die eine Klasse »erbt« alles von der anderen Klasse. Die Klasse, von der geerbt wird, nennt man die »Basisklasse«. Oder man sagt auch: SuperToaster ist von der Klasse Toaster abgeleitet und erbt ihre Eigenschaften und Methoden.

Die Klasse SuperToaster ist damit in ihrer Definition erst mal identisch mit der Klasse Toaster.

Wenn man das so definieren würde:

class SuperToaster(Toaster):

  pass

hätte man damit eine neue Klasse definiert, die genau gleich ist wie die Klasse Toaster. (pass bedeutet so viel wie »nichts weiteres hinzufügen«, es ist ein leerer Befehl und kennzeichnet, dass hier nichts mehr hinzugefügt wird und die Klassendefinition damit vollständig ist).

Man könnte jetzt also auch eingeben:

toasty = SuperToaster(3,"rot")

print toasty

Das Ergebnis wäre genau dasselbe wie vorher bei Toaster. Die Eigenschaften und Methoden von Toaster sind auf SuperToaster übergegangen, sie wurden vererbt. Man kann in diesen Toaster Toast hineintun und es auch toasten.

Aber natürlich ist es nicht sonderlich sinnvoll, eine neue Klasse zu definieren, die genau gleich ist wie die vorherige. Daher kann man die neue Klasse jetzt erweitern.

class SuperToaster(Toaster):
temperatur = 300

Nun haben wir einen Toaster, der sich gleich verhält wie der normale, der aber zusätzlich noch eine Eigenschaft temperatur hat, die am Anfang auf 300 Grad steht. Wir können sie jederzeit verändern:

toasty = SuperToaster(3,"rot")

toasty.temperatur = 250

Aber wir können dem neuen Supertoaster jetzt auch noch eigene Methoden hinzufügen, die er dann zusätzlich zu den vorhandenen von Toaster hat. Zum Beispiel das Temperaturtoasten, das Toasten mit der eingestellten Temperatur:

def temptoasten(self):
if self.temperatur > 500:
return "Alarm: Der Toaster ist zu heiß!"
elif self.temperatur < 100:
return "Das Brot wird nicht getoastet - zu kalt."
else:
return self.toasten()

Hier wird zuerst geprüft, ob die Temperatur zu hoch ist, dann meldet der Toaster, dass er zu heiß ist, oder zu niedrig, dann meldet er, dass er zu kalt ist. Nur wenn die Temperatur stimmt, wird der normale Toastvorgang aufgerufen – und der steht der Klasse ja dank der Vererbung aller Methoden von Toaster zur Verfügung.

Was ist, wenn wir in der Klasse SuperToaster eine neue Funktion definieren, die aber denselben Namen hat wie die Funktion in der Basisklasse (Toaster)? Zum Beispiel:

class SuperToaster(Toaster):
def toasten(self):

usw …

Ganz einfach: Dann wird die geerbte Funktion toasten() von der neu definierten Funktion mit dem gleichen Namen überschrieben. Wenn wir in der Klasse SuperToaster eine eigene Funktion toasten() definieren, dann gilt nur für die damit erzeugten Objekte noch diese neue Funktion – und nicht mehr die geerbte aus der Basisklasse.

Auf die Weise kann man also neue Klassen definieren, die auf vorhandenen Klassen basieren, aber Teile davon durch andere Funktionen ersetzen. So baut man die Variation einer Klasse – zum Beispiel einen Toaster, der im Wesentlichen gleich ist, aber einen ganz anderen Toastmechanismus hat.

Puh … eine ganze Menge war das. Viel, viel Toaster – ich kann verstehen, dass du auf Toast jetzt vielleicht keine Lust mehr hast.

Es ist aber ganz wichtig, dass du die Grundlagen der Objektprogrammierung verstanden hast, denn du wirst später alles mit Objekten programmieren – und wenn du erst einmal verinnerlicht hast, wie es funktioniert, wird es dir ganz natürlich erscheinen und das Programmieren sehr vereinfachen. Zur Praxis geht es dann endlich im nächsten Kapitel mit Objektspielen – da kommt der Spaß dann wieder richtig auf!