Kü /Info Oberstufe OOP - Spieleprogrammierung SJ 2015/2016 Was ist Vererbung und warum sollte man das verwenden? Video: o http://perm.ly/oop-vererbung o http://perm.ly/oop-vererbung-ii Es ist sehr unbefriedigend, große Programmtextabschnitte durch Kopieren in andere Klassen zu übertragen, ohne dass in weiten Teilen auch nur eine Zeile geändert wird (will man nachträglich z.B. dort etwas ändern, so muss man das an vielen Stellen tun und verliert schnell den Überblick). Absolut naheliegend ist, diese Abschnitte in eine eigene „Datei“ auszugliedern, um dann jedes Mal darauf zuzugreifen (oder dafür eigene Prozeduren zu benennen). In der OO ist das geeignete Mittel dafür aber keine Datei, sondern eine neue Klasse. Das ist aber nicht nur einfach eine andere Schreibweise, dahinter steckt viel mehr – es geht um eine neue Art von Abstraktion. Beispiel: Die Spielerklassen bisher beschreiben konkrete Objekte. Nun wird aber von allen Spielerklassen eine übergeordnete Klasse Spieler geschaffen, die alle Attribute und Methoden enthält, die die nun untergeordneten konkreten Spielerklassen gemeinsam hatten. Diese übergeordnete Klasse Spieler beschreibt selbst kein konkretes Objekt (was genau sollte den ein Spieler auch sein ), sie ist wie eine Art „Sammeleimer“ für alle Attribute und Methoden, die die Unterklassen gemeinsam brauchen. Dadurch muss man die Attribute und Methoden nun nur noch einmal in der Oberklasse schreiben und die Unterklassen können dann automatisch darauf zugreifen (mit einer Einschränkung: die Attribute und Methoden müssen public oder protected sein, sind sie auf private gesetzt, so kann eine Unterklasse nicht darauf zugreifen). In den konkreten Spielerklassen wie Kugel und Kachel selbst stehen nur noch die Attribute und Methoden, die nur die spezielle Klasse selbst benötigt. Kü /Info Oberstufe OOP - Spieleprogrammierung SJ 2015/2016 abstract Beschreibt die Oberklasse so wie hier selbst kein konkretes Objekt, sondern ist nur ein „abstrakter“ Sammel-Eimer, so wird die Oberklasse auch als abstract gekennzeichnet. Man verhindert dadurch, dass von ihr konkrete Objekte gebildet werden können. In unserem Fall ist das auch sinnvoll, denn sie dient nur dem Sammeln von Attributen und Methoden, aber ein allgemeines „Spieler-Objekt kann die Leinwand gar nicht verarbeiten, es darf also auch nicht erzeugt werden. Wichtig: eine Oberklasse, die als „abstract“ gekennzeichnet ist, muss mindestens eine abstrakte Methode haben – d.h. eine Methode, die nicht in dieser Klasse selbst implementiert wird, dafür aber durch ihre Kennzeichnung als „abstract“ erzwingt, dass jede Unterklasse sie implementier (siehe Kapitel Probleme…)t. Bsp.: public abstract void test(); <-ohne geschweifte Klammer, nur die Signatur und dann ein Semikolon protected/public Gegenüber der Methode getForm() der ursprünglichen Klassendefinition hat sich außerdem die Angabe zur Sichtbarkeit geändert. Weshalb das notwendig ist, kann man leicht feststellen, wenn man es bei private belässt: Bei dieser Definition kann die Methode, die nun in einer anderen Klasse steht, nicht aufgerufen werden. protected macht eine Methode innerhalb des gesamten Paketes sichtbar, nicht aber nach außen (dafür müsste es auf public gesetzt sein). extends Es ergibt sich das Problem, dass unser Projekt nun zwar eine neue Klasse hat, BlueJ und JAVA aber nichts davon wissen, dass die Spielerklassen ihre Attribute und Methoden von der Klasse Spieler erben sollen. Das müssen wir in den Klassentext einarbeiten. Der Kopf wird ergänzt um extends Spieler . Nun weiß JAVA beim Übersetzen, dass es dort nach den fehlenden Attributen und Methoden nachsehen kann. Probleme, die entstehen, wenn man mit einer Oberklasse Moebel arbeitet Wenn wir die gemeinsamen Methoden in die neue Klasse Spieler ausgegliedert haben und die verkürzte Methode getForm() in der konkreten Spielerklasse – z.B. Kugel– verblieben ist, dann kennt die Klasse Spieler die Methode getForm() nicht. Es gibt aber Methoden in Spieler, die darauf zugreifen! Das muss zu einem Fehler führen. Wir können das auf zwei Arten lösen: 1. Wir erstellen eine eigene Methode getForm() in Spieler, die nichts tut (z.B. leer). In diesem Fall wird die Methode von Spieler durch die erbende Klasse überschrieben. 2. Wir erstellen einen reinen Methodenkopf und fügen ihm das Wort abstract hinzu. In diesem Fall wird unsere Klasse aber notwendig eine abstrakte Klasse, also eine Klasse, von der keine Objekte erzeugt werden können. Viele andere Beispiele für die unter 2. beschriebene Variante finden wir in den von uns verwendeten Grafikklassen, z.B. Ellipse2D, von der selbst keine Objekte erzeugt werden, sondern nur von Ellipse2D.Double und Ellipse2D.Float Kü /Info Oberstufe OOP - Spieleprogrammierung SJ 2015/2016 Merke: In einer Klasse, die als abstract definiert ist, können Methoden ebenfalls als abstract definiert werden. In diesem Falle braucht man für die Methode keine konkrete Implementierung angeben, es reicht der Methodenkopf. Die konkrete Implementierung muss dann aber in allen Unterklassen erfolgen. Beachte: die Methodensuche fängt immer in der Klasse des gerade betrachteten Objektes an und arbeitet sich dann von Oberklasse zu Oberklasse nach oben hin vor, bis sie eine Methode gefunden hat, die passt. Findet man auf dem Vererbungsweg keine passende Methode (also sowohl in der Klasse, in der sie aufgerufen wurde, also auch in einer der Oberklassen), so gibt es eine Fehlermeldung. Die verbleibende Klassendefinition von Kugel ist dann nur noch sehr kurz: import java.awt.Shape; import java.awt.geom.Ellipse2D; public class Kugel extends Spieler public Kugel(){ this.farbe= "green"; this.radius=30.0; this.entfernen=false; this.xPosition = 150.0; this.yPosition = 50.0; this.orientierung=90; this.istSichtbar = true; } public Shape getForm(){ Ellipse2D.Double kreis = new Ellipse2D.Double(xPosition, yPosition, this.radius, this.radius); return kreis; } }