Vererbung Ein wichtiges Konzept der Objektorientierten Programmierung (OOP) ist die Vererbung. Darunter versteht man die Möglichkeit, dass man von einer schon programmierten Klasse eine Unterklasse (oder Subklasse) ableitet, die alle Eigenschaften und Methoden dieser Klasse erhält. Die Subklasse erweitert (engl. extends) also die Oberklasse (die oft auch als Basisklasse oder Superklasse bezeichnet wird). Ein Objekt der Subklasse verfügt dann über mehr Eigenschaften und Methoden als ein Objekt der Superklasse. Der Gedanke, der dahinter steckt, ist verblüffend einfach. Machen wir gleich ein Beispiel. Wir haben die Klasse Dartscheibe entwickelt. Aber man kann damit nur eine Dartscheibe in das Fenster zeichnen und deren Position festlegen. Das ist zunächst alles. Wäre es nicht schön, wenn die Dartscheibe »feststellen« könnte, ob sie vom Dartpfeil getroffen wurde und eine entsprechende Meldung ausgäbe? Wir könnten dazu die Klasse Scheibe ergänzen und verändern. Aber das wäre umständlich und fehleranfällig. Besser ist es die Klasse Scheibe zu erhalten und eine neue Klasse IntelligenteDartscheibe zu schreiben die alles »erbt«, was Dartscheibe »kann«, und dazu mit noch weiteren Methoden oder Attributen versehenwird. IntelligenteDartscheibe ist also eine Dartscheibe. Allerdings ist sie eine spezielle Dartscheibe. Man sagt auch, dass zwischen den Klassen IntelligenteDartscheibe und Dartscheibe eine Ist-Beziehung besteht. Damit IntelligenteDartscheibe alles von Dartscheibe »erbt« muss man ihr das »sagen«. Dazu wird lediglich das Schlüsselwort extends im Kopf der neuen Klasse benötigt: class IntelligenteDartscheibe extends Dartscheibe{ } Damit hat die Klasse IntelligenteDartscheibe alle Eigenschaften und Methoden von Dartscheibe »geerbt«. Die Vererbung hat den Vorteil, dass die Klasse IntelligenteDartscheibe recht kurz wird und nur Ergänzungen oder Veränderungen enthält. Allerdings kann eine Klasse nur von einer Oberklasse »erben« und nicht von mehreren. (Hinter extends darf man also nur eine Klasse angeben). In Java gibt es nur Einfach-Vererbung und keine Mehrfach-Vererbung. Erzeugt man ein Objekt ida von der Klasse IntelligenteDartscheibe, so kann man mit ida.nimmDieGrafik(), und ida.zeichneDich() die Methoden aus der Klasse Dartscheibe aufrufen. Soll ida weitere Methoden haben, wie nimmDenPfeil(), hatGetroffen(), oder meldeTreffer(), so schreibt man diese genauso in die Klasse IntelligenteDartscheibe, wie bisher schon Methoden in eine Klasse eingetragen worden sind. Man kann natürlich auch neue Variablen für die (neue) Unterklasse definieren und dort entsprechend eintragen. Das ist im Prinzip schon alles. Die Vererbung kann beliebig weitergeführt werden. Eine weitere Klasse könnte so heißen: SuperIntelligenteDartscheibe extends IntelligenteDartscheibe { } Ein Objekt subida von dieser Klasse, kann dann sowohl alle Methoden aus der Klasse Dartscheibe als auch alle Methoden aus der Klasse IntelligenteDartscheibe ausführen und darüber hinaus noch weitere »eigene« Methoden. Übrigens, um eine Klasse Unter von einer Klasse Ober abzuleiten, muss man nicht einmal wissen, wie die Klasse Ober programmiert ist. Es genügt ihre Methoden zu kennen und die Datei Ober.class zur Verfügung haben. Die Methoden findet man in einer dazu gehörigen Klassendokumentation. Ein Beispiel für Klassendokumentationen ist die Dokumentation der Klassen aus der Klassenbibliothek hiddenClasses. Wenn eine Methode der Oberklasse verändert werden muss, kann sie in der Unterklasse neu deklariert werden. Dieses Verfahren nennt man Überschreiben oder Überlagern. (Dabei muss man darauf achten, dass sowohl der Methodenname als auch die Parameter und ihre Reihenfolge genauso gewählt sind wie bei der zu überschreibenden Methode der Oberklasse.) Möchte man in der abgeleiteten Klasse eine Methode der Oberklasse aufrufen, so verwendet man ähnlich wie beim Selbstaufruf this dafür ein Schlüsselwort, nämlich super. (z.B. super.zeichneDich() vgl. this.zeichneDich()) Beispiel: import hiddenClasses.*; import java.awt.*; class Scheibe{ Grafik g; ... public void zeichneDich(){ g.drawOval(360,360,80,80); g.drawOval(370,370,60,60); g.drawOval(380,380,40,40); g.drawOval(390,390,20,20); } } import hiddenClasses.*; import java.awt.*; class BunteScheibe extends Scheibe{ public void zeichneDich(){ g.setColor(Color.blue); g.fillOval(360,360,80,80); g.setColor(Color.red); g.fillOval(370,370,60,60); g.setColor(Color.green); g.fillOval(380,380,40,40); g.setColor(Color.black); g.fillOval(390,390,20,20); g.setColor(Color.black); super.zeichneDich(); } } Man darf in der Unterklasse auch Methoden der Oberklasse aufrufen, die in der Unterklasse überschrieben werden. Wird zum Beispiel die Methode zeichneDich() in der Unterklasse überschrieben, so kann man in der Unterklasse mit super.zeichneDich() die alte Methode zeichneDich() und mit this.zeichneDich() die neue Methode zeichneDich aufrufen. Wird eine (überschriebene) Methode (zum Beispiel zeichneDich()) weder in der Unterklasse noch in der Oberklasse, sondern von einer anderen Klasse aus aufgerufen, so muss wie immer der Objektname vor dem Methodennamen angegeben werden. Wenn das Objekt ein Objekt der Unterklasse ist, wird die (neue) Methode der abgeleiteten Klasse ausgeführt. Falls das Objekt ein Objekt der Oberklasse ist, wird dagegen die (alte) Methode der Oberklasse ausgeführt. Beispiel: meineScheibe.zeichneDich() Ist meineScheibe ein Objekt der Klasse BunteScheibe, so wird eine bunte Scheibe gezeichnet. Ist meineScheibe dagegen ein Objekt der Klasse Scheibe, so werden nur die schwarzen Kreislinien gezeichnet.