27.5 Kreis und Quadrat erben von der abstrakten Klasse Figur |
|
Die abstrakte Klasse Figur | Für den
Namen der Klasse, von der Quadrat und Kreis erben sollen wählen wir Figur
und drücken damit auch im Namen schon aus, dass es sich hier um eine
Verallgemeinerung von einem Quadrat und einem Kreis handelt. Wir
beschreiben die neue Situation zunächst in UML und erläutern dann noch
einige Besonderheiten.
|
![]() |
|
Das
meiste in der UML-Darstellung unserer kleinen Hierarchie ist
selbsterklärend. Anderes verdient einer genaueren Betrachtung.
Wir haben in der Klasse Figur eine Methode zeigeDich(Graphics g), sie soll das Zeichnen übernehmen soweit dies möglich ist für eine Figur, von der wir noch gar nicht wissen, ob sie ein Kreis oder ein Quadrat ist. Das einzige, was getan werden kann, ist die Farbe für den Zeichenstift zu setzen. Den Rest erledigt dann zeichne(Graphics g), das wegen der unterschiedlichen Funktionalität aber erst in Quadrat und Kreis implementiert werden kann. Andererseits ruft zeigeDich(Graphics g) die Methode zeichne(Graphics g) auf, weshalb diese Methode in Figur bekannt sein muss. Den Konflikt lösen wir dadurch, dass wir in Figur lediglich die Signatur von zeichne(Grahics g) festlegen, ihr also noch keinen Code geben. Damit wird diese Methode abstrakt (Java: abstract). In UML wird dies durch die kursive Schreibweise angezeigt. Nun gilt aber, und das haben wir bereits gelernt, eine Klasse ist abstrakt, wenn sie nur eine abstrakte Methode enthält. Die Klasse Figur ist also abstrakt, weshalb wir ihren Namen in UML ebenfalls kursiv schreiben. Da Kreis und Quadrat von Figur erben, müssen beide die geerbte abstrakte Methode zeichne(Graphics g) auf ihre spezifische Weise implementieren um nicht selbst auch abstrakt zu sein. Und noch etwas ist von Interesse: Wir haben gelernt, dass man Konstruktoren benutzt um Instanzen ihrer Klassen zu erzeugen. Warum hat dann Figur einen Konstruktor, wenn Figur doch abstrakt ist und von ihr keine Instanzen erzeugt werden können? Dass wir aber Instanzen sogar von Interfaces wie etwa von Runnable erzeugen können, haben wir auch schon erfahren, wir müssen dabei lediglich die abstrakten Methoden implementieren. Und eine weiteren Vorteil von Konstruktoren in abstrakten Klassen werden wir kennen lernen, das lässt sich allerdings erst so richtig anhand des Java-Quelltextes unserer drei Klassen nachvollziehen. |
|
Download: Figur.java |
|
Bemerkungen | Der
Konstruktor organisiert für eine Figur die Festlegung des Mittelpunktes
und der Farbe. Wie eine abstrakte Methode geschrieben wird sehen wir an
dem gelb unterlegten Text.: Die Signatur wird festgelegt, nach der
Parameterliste kommen aber keine Blockklammern, wie wir es von
gewöhnlichen Methoden gewohnt sind, sondern es folgt lediglich ein
Semikolon. Dafür muss vor den Rückgabetyp, hier void, das Wort
abstract
stehen. Wie schon erwähnt wurde, muss dann auch die ganze Klasse abstakt
sein. Der Compiler erkennt dies daran, dass dem Wort
class
im Kopf ebenfalls das Wort
abstract
vorgesetzt wird.
Der Quellcode, mit
Dokumentationskommentaren versehen kann heruntergeladen werden, er wird im
Verzeichnis abgelegt und compiliert. |
Download: Quadrat.java |
|
Kommentar //1 | Beim
Aufruf des Konstruktors werden diesem die Koordinaten des Mittelpunktes,
die Seitenlänge und die Farbe übergeben. Der Konstruktor ruft mit super
den Konstruktor der Vaterklasse auf, wobei die Parameter von super denen
des aufgerufen Konstruktors von
figur entsprechen müssen. Das
Setzen des Mittelpunktes und der Farbe werden dort, also in
figur
erledigt, so dass im Konstruktor von Quadrat eigentlich nur noch das
Setzen der Seitenlänge organisiert werden muss. Statt aber einfach
this.seite = seite;
zu schreiben verwenden wir stattdessen die Methode
setSeite(int seite),
die weiter unten implementiert ist. Dass dies von Vorteil ist sehen wir
gleich. |
Kommentar //2 | Um zu
vermeiden, dass die Seitenlänge einen unsinnigen, z.B. negativen Wert
erhält, wird das setzen der Seitenlänge nur unter der Bedingung gemacht,
dass die Seitenlänge nicht negativ ist. Jetzt erkennen wir, dass es Sinn
macht, diese Methode auch im Konstruktor zu verwenden. Würden wir dies
nicht tun, müssten wir die Zusicherung dass die Seitenlänge einen
vernünftigen Wert hat, auch im Konstruktor und damit doppelt
implementieren. |
Kommentar //3 | Die Methode zeichne(Graphics g) bekommen im Objekt g den Graphic-Kontext übergeben auf den gezeichnet werden kann. Für g wird dann die Graphics-Methode fillrect(...) aufgerufen. Diese Methode zeichnet ein gefülltes Rechteck in der Farbe, die g in der Methode zeigeDich(Graphics g) in figur bekommen hat. Die ersten beiden Parameter der fillrect(...)-Methode geben die x- und y-Koordinate des linken oberen Eckpunktes des Rechtecks an., die restlichen beiden Parameter seine Breite und Höhe. Sind die beiden letzten Parameterwerte gleich, so handelt es sich bei dem Rechteck um ein Quadrat. |
Signatur der Methode
fillrect(..)
|
|
Die Datei
Quadrat.java
im Download ist wieder mit Dokumentationskommentaren versehen. Speichern
Sie Quadrat.java wie schon
figur.java im Verzeichnis
tauglichkeitstester\figur
ab und kompilieren Sie die Klasse
Quadrat. |
|
Download: Kreis.java |
Die Klasse Kreis lässt sich analog zur Klasse Quadrat implementieren. Machen Sie das als Übung und schlagen Sie in der Java-Dokumentation nach, wenn Sie wissen wollen, wie man eine Ellipse bzw. einen Kreis zeichnet. |
zu | 27.5.1 Tests der Klassen Quadrat und Kreis durch eine Test-GUI |
zur Startseite | www.pohlig.de (C) MPohlig 2004 |