Python Tutorial
- jetzt Python programmieren lernen

Vererbung und Python

Vererbung und OOP geht Hand in Hand. Aber warum überhaupt? Nehmen wir an, wir wollen eine allgemeine Klasse zusätzlich zu unserer speziellen Klasse "Auto". In der allgemeinen Klasse "Fahrzeug" stecken dann Daten wie Beispielsweise "Maximalgeschwindigkeit" und "Sitzplaetze". Diese allgemeinen Daten gelten für alle Fahrzeuge wie Autos als auch Motorrad.

Wir können nun also von der Klasse "Auto", die wir bisher "BauPlanAuto" genannt haben von der noch allgemeineren Klasse "BauPlanFahrzeug" Daten "erben". Das spart natürlich Zeit.

Aufbau der Vererbung in Python

Als erstes definieren wir genauso wie bisher unsere allgemein Klasse "Fahrzeug".

class Fahrzeug:
	sitzplaetze = 4
	maxGeschwindigkeit = 100

Unsere bisherige Klasse "BauPlanAuto" nennen wir in diesem Beispiel der Einfachheit halber "Auto".

class Fahrzeug:
	sitzplaetze = 4
	maxGeschwindigkeit = 100
class Auto:
	farbe = "rot"
	geschwindigkeit = 0
	def __init__(self, kraftstoff="Benzin"):
		self.kraftstoff = kraftstoff
borgward = Auto()

Wie bekommt nun unsere spezielle Klasse "Auto" mit, dass es die Daten (und später auch Methoden) der allgemeinen Klasse "Fahrzeug" über Vererbung nutzen soll? Dazu wird bei der Definition der Klasse "Auto" danach in Klammern die allgemein Klasse geschrieben:

class Fahrzeug:
	sitzplaetze = 4
	maxGeschwindigkeit = 100
class Auto(Fahrzeug):
	farbe = "rot"
	geschwindigkeit = 0
	def __init__(self, kraftstoff="Benzin"):
		self.kraftstoff = kraftstoff
borgward = Auto()

Wir können also den Code wie folgt lesen. Unsere Klasse Auto ist ein Fahrzeug. Und wir können direkt schon auf die Grundlegenden Werte wir gewohnt zugreifen.

…
borgward = Auto()
print(borgward.maxGeschwindigkeit)
print(borgward.sitzplaetze)

Jetzt können wir die Variablen auch ändern. Dazu können wir entweder in unserer "Auto"- wir auch in unserer "Fahrzeug"-Klasse eine entsprechende Methode integrieren.

class Fahrzeug:
	sitzplaetze = 4
	maxGeschwindigkeit = 100
class Auto(Fahrzeug):
	farbe = "rot"
	geschwindigkeit = 0
	def __init__(self, kraftstoff="Benzin"):
		self.kraftstoff = kraftstoff
	def sitzplaetzeFestlegen(self, sitzplaetzeNeu):
		self.sitzplaetze = sitzplaetzeNeu
borgward = Auto()
print(borgward.sitzplaetze)
borgward.sitzplaetzeFestlegen(2)
print(borgward.sitzplaetze)

Rufen wir nun unser Programm auf, erhalten wir als Ausgabe erst die Standardanzahl 4, korrigieren dann für das Auto die Anzahl auf 2 und bekommen bei der nächsten Ausgabe die Sitzplatzanzahl 2.

Vererbung und Methoden

Jetzt kann man sich natürlich fragen, wo diese Methode integriert werden soll. In der allgemeinen Klasse "Fahrzeug" oder in der Klasse "Auto". Hier immer überlegen, wo man am meisten Tipparbeit sich in Zukunft spart. Erzeugen wir eine weitere Klasse wie z.B. "Motorrad" oder "Flugzeug", dann sollten wir auch dort die Anzahl der verfügbaren Sitzplätze ändern können.

Also wäre das eine gute Methode, die in der allgemeinen Klasse integriert gehört, die dann alle anderen zum Vererben zur Verfügung steht. Verschieben wir diese Klasse in unsere Allgemein Klasse:

class Fahrzeug:
	sitzplaetze = 4
	maxGeschwindigkeit = 100
	def sitzplaetzeFestlegen(self, sitzplaetzeNeu):
		self.sitzplaetze = sitzplaetzeNeu
class Auto(Fahrzeug):
	farbe = "rot"
	geschwindigkeit = 0
	def __init__(self, kraftstoff="Benzin"):
		self.kraftstoff = kraftstoff
borgward = Auto()
print(borgward.sitzplaetze)
borgward.sitzplaetzeFestlegen(2)
print(borgward.sitzplaetze)

Das tolle ist, dass wir nur die Klasse verschieben mussten aber der Aufruf der Methode exakt gleichbleibt.

Vererbung und Konstruktoren

Auch unsere allgemeinen Klassen können über Konstruktoren verfügen. Nehmen wir an, dass die Maximalgeschwindigkeit einmal am Anfang beim Erzeugen der Instanz gesetzt werden sollte. Vom grundsätzlichen Aufbau ändert sich da nichts.

class Fahrzeug:
	sitzplaetze = 4
	def __init__(self):
		self.maxGeschwindigkeit = 100
	def sitzplaetzeFestlegen(self, sitzplaetzeNeu):
		self.sitzplaetze = sitzplaetzeNeu

Was passiert mit dem Konstruktor der Oberklasse, wenn wir diesen nutzen wollen? Rufen wir unser erweitertes Programm einfach auf.

class Fahrzeug:
	sitzplaetze = 4
	def __init__(self):
		self.maxGeschwindigkeit = 100
	def sitzplaetzeFestlegen(self, sitzplaetzeNeu):
		self.sitzplaetze = sitzplaetzeNeu
class Auto(Fahrzeug):
	farbe = "rot"
	geschwindigkeit = 0
	def __init__(self, kraftstoff="Benzin"):
		self.kraftstoff = kraftstoff
borgward = Auto()
print(borgward.maxGeschwindigkeit)

Wir bekommen die Fehlermeldung:

AttributeError: Auto instance has no attribute 'maxGeschwindigkeit'

Wir müssen also den "Konstruktor" unserer Oberklasse "Fahrzeug" einmal aufrufen. In unserer Klasse "Auto" müssen wir einmal in dessen Konstruktor den Konstruktor der Oberklasse "Fahrzeug" auf. Dazu benötigen wir immer die anfangs ungewohnten Angaben von __init__(self):

class Fahrzeug:
	sitzplaetze = 4
	def __init__(self):
		self.maxGeschwindigkeit = 100
	def sitzplaetzeFestlegen(self, sitzplaetzeNeu):
		self.sitzplaetze = sitzplaetzeNeu
class Auto(Fahrzeug):
	farbe = "rot"
	geschwindigkeit = 0
	def __init__(self, kraftstoff="Benzin"):
		Fahrzeug.__init__(self)
		self.kraftstoff = kraftstoff
borgward = Auto()
print(borgward.maxGeschwindigkeit)

Führen wir jetzt unser Programm aus, funktioniert es ohne Fehlermeldung. Allerdings wäre es Sinnvoll, die Maximalgeschwindigkeit mitzugeben beim Initialisieren.

Erweitern wir die entsprechenden Bereiche:

class Fahrzeug:
	sitzplaetze = 4
	def __init__(self, maxGeschwindigkeit=100):
		self.maxGeschwindigkeit = maxGeschwindigkeit
	def sitzplaetzeFestlegen(self, sitzplaetzeNeu):
		self.sitzplaetze = sitzplaetzeNeu
class Auto(Fahrzeug):
	farbe = "rot"
	geschwindigkeit = 0
	def __init__(self, kraftstoff="Benzin", maxGeschwindigkeit=120):
		Fahrzeug.__init__(self, maxGeschwindigkeit)
		self.kraftstoff = kraftstoff
borgward = Auto("Diesel", 110)
print(borgward.maxGeschwindigkeit)

Um unsere Klasse "Fahrzeug" noch abzurunden, packen wir auch den "Kraftstoff" mit dazu und nehmen diesen aus der spezielleren Klasse "Auto" raus. Der Kraftstoff ist ja für alle unsere Fahrzeuge notwendig und somit gehört diese in die Oberklasse "Fahrzeug"

class Fahrzeug:
	sitzplaetze = 4
	def __init__(self, kraftstoff="Benzin", maxGeschwindigkeit=100):
		self.kraftstoff = kraftstoff
		self.maxGeschwindigkeit = maxGeschwindigkeit
	def sitzplaetzeFestlegen(self, sitzplaetzeNeu):
		self.sitzplaetze = sitzplaetzeNeu
class Auto(Fahrzeug):
	farbe = "rot"
	geschwindigkeit = 0
	def __init__(self, kraftstoff="Benzin", maxGeschwindigkeit=120):
		Fahrzeug.__init__(self, kraftstoff, maxGeschwindigkeit)
borgward = Auto("Diesel")
print(borgward.maxGeschwindigkeit)
print(borgward.kraftstoff)

Jetzt haben wir schon eine schöne Oberklasse. Zum Umsetzen des neuen Wissens einfach eine weitere Klasse "Motorrad" integrieren, dass alle Eigenschaften (Variablen) und Methoden (Funktionen) der Oberklasse "Fahrzeug" erbt. Bitte testen, vor man im folgenden Mustercode nachschaut.

class Fahrzeug:
	sitzplaetze = 4
	def __init__(self, kraftstoff="Benzin", maxGeschwindigkeit=100):
		self.kraftstoff = kraftstoff
		self.maxGeschwindigkeit = maxGeschwindigkeit
	def sitzplaetzeFestlegen(self, sitzplaetzeNeu):
		self.sitzplaetze = sitzplaetzeNeu
class Auto(Fahrzeug):
	farbe = "rot"
	geschwindigkeit = 0
	def __init__(self, kraftstoff="Benzin", maxGeschwindigkeit=120):
		Fahrzeug.__init__(self, kraftstoff, maxGeschwindigkeit)
class Motorrad(Fahrzeug):
	def __init__(self, kraftstoff="Benzin", maxGeschwindigkeit=120):
		Fahrzeug.__init__(self, kraftstoff, maxGeschwindigkeit)
borgward = Auto("Diesel")
print(borgward.maxGeschwindigkeit)
print(borgward.kraftstoff)
vespa = Motorrad("Benzin", 70)
print(vespa.maxGeschwindigkeit)
print(vespa.kraftstoff)