A Byte of Python

Vererbung

Eine der Hauptvorzüge objektorientierter Programmierung ist die Möglichkeit der Wiederverwendung von Programmcode, und eine Weise, mit der dies erreicht wird, ist durch den Mechanismus der Vererbung. Vererbung kann man sich am besten als eine mit Klassen realisierte Beziehung zwischen Datentypen und Unterdatentypen vorstellen.

Angenommen, Sie wollen ein Programm schreiben, das die Dozenten und Studenten an einer Hochschule verwaltet. Diese beiden Personengruppen haben einige gemeinsame Merkmale wie Name, Alter und Adresse. Sie haben auch einige spezielle Merkmale wie Gehalt, Vorlesungen und Beurlaubungen für Dozenten und Prüfungsnoten und Studiengebühren für Studenten.

Sie können zwei unabhängige Klassen für die beiden Typen und Prozesse anlegen, aber dies würde bedeuten, dass Sie, wenn Sie ein neues gemeinsames Merkmal hinzufügen wollen, es bei jeder der beiden voneinander unabhängigen Klassen tun hinzufügen müssen. Das wird sehr schnell unhandlich.

Eine bessere Lösung besteht darin, eine gemeinsame Klasse namens SchulMitglied anzulegen, und dann die Klasssen für Dozenten und Studenten von dieser Klasse erben zu lassen, d.h. sie werden zu Unterdatentypen dieses Datentyps (dieser Klasse) gemacht, und wir können diesen Unterdatentypen dann weitere besondere Merkmale hinzufügen.

Dieser Ansatz hat viele Vorteile. Wenn wir der Klasse SchulMitglied Funktionalität hinzufügen oder diese ändern, dann spiegelt sich dies automatisch in den Unterdatentypen wieder. Zum Beispiel können Sie ein neues Feld für die Nummer einer Identitätskarte sowohl für Dozenten als auch für Studenten hinzufügen, indem Sie dies einfach in der Klasse SchulMitglied ergänzen. Änderungen an den Unterdatentypen haben jedoch keine Auswirkung auf andere Unterdatentypen. Ein weiterer Vorteil besteht darin, dass man auf ein Objekt der Klasse Dozent oder Student auch als ein Objekt der Klasse SchulMitglied Bezug nehmen kann, was in einigen Situationen nützlich sein könnte, z. B. wenn man die Anzahl der Mitglieder der Hochschule zählen möchte. Diese Möglichkeit, einen Unterdatentyp in jeder Situation, wo ein Elterndatentyp erwartet wird, ersetzen zu können, d.h. ein Objekt als eine Instanz der Elternklasse behandeln zu können, wird Polymorphismus genannt.

Beachten Sie auch, dass wir den Programmcode der Elternklasse wiederverwenden, dass wir ihn also nicht in den verschiedenen Klassen wiederholen müssen, wie wir es hätten tun müssen, wenn wir unabhängige Klassen benutzt hätten.

Die Klasse SchulMitglied wird in dieser Konstellation auch als die Basisklasse oder die Superklasse bezeichnet. Die Klassen Dozent und Student werden die abgeleiteten Klassen oder Subklassen genannt.

Hier ist nun das Beispiel als Programm.

Verwendung von Vererbung

Beispiel 11.5. Verwendung von Vererbung (vererbung.py)

				
#!/usr/bin/python

class SchulMitglied:
	'''Repraesentiert ein beliebiges Mitglied der Hochschule.'''
	def __init__(self, name, alter):
		self.name = name
		self.alter = alter
		print '(SchulMitglied %s initialisiert)' % self.name

	def auskunft(self):
		'''Gib Auskunft ueber das Mitglied.'''
		print 'Name: "%s" Alter: "%s"' % (self.name, self.alter),

class Dozent(SchulMitglied):
	'''Repraesentiert einen Dozenten der Hochschule.'''
	def __init__(self, name, alter, gehalt):
		SchulMitglied.__init__(self, name, alter)
		self.gehalt = gehalt
		print '(Dozent %s initialisiert)' % self.name

	def auskunft(self):
		SchulMitglied.auskunft(self)
		print 'Gehalt: "%d Euro"' % self.gehalt

class Student(SchulMitglied):
	'''Repraesentiert einen Studenten der Hochschule.'''
	def __init__(self, name, alter, note):
		SchulMitglied.__init__(self, name, alter)
		self.note = note
		print '(Student %s initialisiert)' % self.name

	def auskunft(self):
		SchulMitglied.auskunft(self)
		print 'Letzte Pruefungsnote: "%1.1f"' % self.note

d = Dozent('Mrs. Shrividya', 40, 30000)
s = Student('Swaroop', 22, 1.7)

print # gib eine Leerzeile aus

mitglieder = [d, s]
for mitglied in mitglieder:
	mitglied.auskunft() # geht bei Dozenten und Studenten
				
				

Ausgabe

				
$ python vererbung.py
(SchulMitglied Mrs. Shrividya initialisiert)
(Dozent Mrs. Shrividya initialisiert)
(SchulMitglied Swaroop initialisiert)
(Student Swaroop initialisiert)

Name: "Mrs. Shrividya" Alter: "40" Gehalt: "30000 Euro"
Name: "Swaroop" Alter: "22" Letzte Pruefungsnote: "1.7"
				
				

So funktioniert es

Um Vererbung zu benutzen, geben wir die Namen der Basisklassen in einem Tupel an, das in der Klassendefinition dem Namen der Klasse folgt. Danach ist zu beachten, dass die __init__-Methode der Basisklasse unter Benutzung der self-Variable explizit aufgerufen wird, damit der Anteil des Objekts, der von der Basisklasse bereitgestellt wird, initialisiert werden kann. Es ist sehr wichtig, sich dies zu merken - Python ruft nicht automatisch den Konstruktor der Basisklasse auf; Sie müssen ihn selber explizit aufrufen.

Wir sehen hier auch, dass wir Methoden der Basisklasse aufrufen können, indem wir den Namen der Basisklasse mit einem Punkt voranstellen, und dann die Variable self zusammen mit den anderen Parametern der Methode übergeben.

Beachten Sie, dass wir Instanzen von Dozent und Student einfach wie Instanzen von SchulMitglied behandeln, wenn wir die auskunft-Methode der Klasse SchulMitglied benutzen.

Beachten Sie auch, dass die auskunft-Methode der Subklassen aufgerufen wird, und nicht die auskunft-Methode der Superklasse SchulMitglied. Man kann dies so verstehen, dass Python immer zuerst versucht, Methoden der jeweiligen Klasse zu finden, die in diesem Fall vorhanden sind. Wenn die Methode nicht gefunden wird, dann fängt Python an, die Methoden der zugehörigen Basisklassen eine nach der anderen durchzugehen, in der Reihenfolge, wie sie in dem Tupel in der Klassendefinition angegeben ist.

Eine Anmerkung noch zur Sprechweise - wenn mehr als eine Klasse in dem Tupel der Basisklassen angegeben ist, von denen die Klasse erbt, dann spricht man von Mehrfachvererbung.