Sie sind auf Seite 1von 29

Objektorientierte Modellierung mit BlueJ

Uwe Debacher 2008 -1- Hansa-Gymnasium

1. Ein Grafiksystem in Java


Zur Thematik
Inhaltliches Ziel des aktuellen Semesters ist die Erstellung eines Grafiksystems in Java. Gedacht ist
an ein vektororientiertes Grafiksystem, ein zweidimensionales Wohnungseinrichtungssystem für die
Kunden eines Möbelhauses.
Es eignet sich gut, um in Verfahren der objektorientierten Modellierung und Programmierung
einzuführen. Als Benutzungsoberfläche wird die Entwicklungsumgebung BlueJ genutzt, die explizit
für die Lehre entwickelt wurde und kostenfrei verfügbar ist (http://www.bluej.org).
Mit dieser Entwicklungsumgebung kannst du zunächst mit einem stark reduzierten, vereinfachten
Modell interagieren und damit die notwendigen Grundvorstellungen von Objekten, Attributen,
Methoden, Nachrichten und Klassen aufbauen.
Anschließend setzt du den Programmquellcode in Beziehung zum Verhalten der Objekte und
erweitern ihn, um das System schrittweise auszubauen. Dies geschieht in mehreren Schritten:
1. interaktiv Gruppen von Möbeln erstellen
2. Klassen für Möbelgruppen erstellen, Aggregation (Teile-Ganzes-Beziehung) thematisieren;
Beispiele: Schrankwand zunächst interaktiv erstellen, anschließend Klasse Schrankwand mit n
Schränken. Ebenso z.B. Sitzgruppe, Doppelbett, Computerarbeitsplatz, Computerraum.
3. bestehende Klassen ausbauen
4. neue Möbelklassen hinzufügen

Vektorformat vs. Pixelformat


Im Computerbereich sind zwei Arten von Anwendungen bzw. Dateiformaten gebräuchlich.
• Einerseits Malprogramme wie MS-Paint, bei denen alle
Abbildungen aus einzelnen Punkten zusammengesetzt
sind. Man kann in der Bedienoberfläche dieser
Programme zwar Linien, Rechtecke oder Kreise zum
Zeichnen auswählen, sowie die Objekte aber dargestellt
sind kann die Anwendung diese nicht mehr als solche
Verschieben, da nur Menge von Punkten gezeichnet
wird. Der Bildschirmpunkt ist das einzige Objekt,
welches diese Anwendungen wirklich kennen.
Nachträglich ist es auch nicht mehr möglich die Farbe
oder die Breite einer Linie zu verändern.
Beim Vergrößern eines derartig gemalten Bildes werden
schräge oder runde Linien zu recht stufigen Gebilden.

• Deutlich flexibler sind die Zeichenprogramme, wie z.B. StarOffice Draw. Derartige Programme
besitzen intern eine Beschreibung für Objekte wie
Linien, Kreise und Rechtecke. Du kannst daher die
Objekte jederzeit erneut auswählen und jede ihrer
Eigenschaften verändern.
Auch beim Vergrößern eines Ausschnittes bleiben alle
Linien glatt und gleichmäßig, da die Darstellung des
Objektes der neuen Auflösung angepasst wird. Da auch
die Druckqualität entsprechend hoch ist, arbeiten alle
Konstruktionsprogramme objektorientiert.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 -2- Hansa-Gymnasium

Normzeichen für das Zeichnen von Möbeln

Für das Zeichnen von Möbeln gibt es genormte Darstellungen, die auch für das vorliegende Projekt
zur Anwendung kommen sollen.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 -3- Hansa-Gymnasium

2. Klassen und Objekte


Bevor eine Grafikanwendung wie das beschriebene Möbelsystem realisierbar ist müssen erst einmal
ein Paar Grundlagen geklärt werden, vor allem die Begriffe Klasse und Objekt.

Einführung
Zur Einführung kannst du dir die Elemente eines Computer-Desktops ansehen: Buttons auf der
Taskleiste, Programmlinks, Dokumente, usw.

Fragestellungen:
• Was seht ihr?
• Welche Gemeinsamkeiten haben die einzelnen Elemente auf dem Desktop?
• Welche Eigenschaften haben diese Elemente?
• Was kann ich mit diesen Elementen machen?

Ergebnisse:
• Es gibt Gruppen gleichartiger Elemente, z.B. Buttons, Dokumente, Programme und Links.
• Die Gruppen werden als Klassen bezeichnet.
• Die einzelnen Elemente sind die Objekte der jeweiligen Klasse.
• Die Elemente bestehen u.a. aus Icon und Namen (Attribute).
• Sie reagieren unterschiedlich (Programme werden gestartet, Dokumente geöffnet), man kann sie
verschieben usw. (Methoden).

Weitere mögliche Beispiele sind:


• Mediator
• Textverarbeitung (Absätze, Zeichen)
• Präsentationsprogramm
• eigentlich jedes Programm mit einer grafischen Benutzeroberfläche.

Aufgabe: Nenne Beispiele für Klassifizierungen aus dem täglichen Leben!

Beispiele:
• Körperformen (s. Arbeitsblatt Körperformen)
• Tiere, Pflanzen, Menschen,
• Auto und ein konkretes Auto zur Unterscheidung zwischen Klasse und Exemplar (Instanz).

Der natürliche Umgang mit Dingen/Objekten


Natürlicherweise sind wir den Umgang mit Dingen gewohnt. Wir können Dinge sehen oder fühlen,
aber Dinge können auch nur in der Vorstellung bestehen. Über die Dinge des Lebens ließe sich
weiter philosophieren, aber das muss an anderen Stelle geschehen.

Im Umgang mit den Dingen haben wir gelernt:


• Dinge besitzen Eigenschaften,
• Dinge können sich verändern,
• Veränderungen haben eine Ursache, wenn wir sie auch nicht in jedem Fall verstehen.

Wir können abstrahieren. So haben wir beispielsweise erkannt:


• Dinge können aus Teilen bestehen
• Dinge können kategorisiert werden.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 -4- Hansa-Gymnasium

Genau dies spielt auch im Zusammenhang mit Klassen und Objekten eine Rolle.
Modellbildung
Programmierung ist ein Modellbildungsprozess. Bei allen Modellbildungen betrachtet man einen
Ausschnitt der realen Welt und versucht ihn mit einem formalen System, z.B. einer
Computersprache zu beschreiben.
Wesentlicher Teil des Modellbildungsprozesses ist es diejenigen Objekte zu identifizieren, die auch
im Modell eine Rolle spielen. Im weiteren Verlauf der Modellbildung geht es dann darum die
identifizierten Objekte zu kategorisieren und in Klassen zusammen zu fassen.

Klasse
Klassen fassen Objekte mit gleichen Eigenschaften und gleichem Verhalten zusammen. Schreiben
wir in Java eine Klassendefinition, dann beschreiben wir in ihr, welche Eigenschaften und welches
Verhalten ein Objekt hätte, das dieser Klasse zugehören soll, wenn wir es erzeugen würden.

Objekt
Ein Objekt ist ein konkretes Exemplar, eine Instanz, die zu einer Klasse gehört.

Deutlich werden die Begriffe, wenn man auf alltägliche Beispiele abhebt. Relativ wichtig in
unserem Alltag ist die Klasse Automobil, die bestimmte Fahrzeuge zusammenfasst.
Der alte Bully des Deutschlehrers ist dann ein konkretes Objekt, eine Instanz der Klasse Auto,
genau wie der Mercedes des Physiklehrers ein Objekt darstellt.

Im Zusammenhang mit der Textverarbeitung lassen sich dann Klassen wie Absatz, Zeichen oder
Seite identifizieren. Eine konkrete Instanz der Klasse Absatz und damit ein Objekt der
Textverarbeitung wäre dann der vorliegende Textteil.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 -5- Hansa-Gymnasium

3. Objekte und Klassen mit BlueJ


Arbeiten mit der Oberfläche von BlueJ
Die Arbeit mit BlueJ erlaubt einen einfachen
Umgang mit Klassen und Objekten in der
Programmiersprache Java. Beim ersten Start sieht
die Oberfläche von BlueJ sehr aufgeräumt aus.

Für die ersten Schritte benötigst du die Menüleiste, in der sich der Punkt Projekt findet. In dem
Projekt-Menü findet du den Unterpunkt Projekt
öffnen... über den du einen Dialog zum Öffnen von
BlueJ-Projekten erhält. Im Verzeichnis Abschnitt 3
der Materialien zu dieser Einführung findet sich u.a.
das BlueJ-Projekt Figuren. Nach dem Laden dieses
Projektes ergibt sich das folgende Bild.

Im Hauptfenster von BlueJ ist ein Diagramm zu


sehen, das die Klassen des Projektes Figuren und
ihren Zusammenhang darstellt. Konkret sind dies
die Klassen
• Dreieck,
• Quadrat,
• Kreis und
• Leinwand.
Die Pfeile machen deutlich, dass die drei geometrischen Klassen die Klasse Leinwand benutzen.

Klicke jetzt mit der rechten Maustaste auf die Klasse


Kreis und wähle aus dem Kontextmenü den ersten
Menüpunkt new Kreis() aus. Im anschließenden
Dialog, der dich nach einem Namen für die Instanz
von Kreis fragt kannst du einfach auf OK klicken
und damit die Vorgabe kreis1 akzeptieren. Es sollte
sich jetzt das folgende Bild ergeben.

In der Objektleiste von BlueJ ist jetzt die Instanz


kreis1 der Klasse Kreis abgelegt. Vermutlich erfüllt
diese Darstellung noch nicht deine Erwartungen, da
kein Kreis auf dem Bildschirm zu sehen ist.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 -6- Hansa-Gymnasium

Methoden aufrufen
Um den zugehörigen Kreis auf den Bildschirm zu bekommen klickst
du mit der rechten Maustaste auf das Objekt in der Objektleiste,
worauf sich sein Kontextmenü öffnet.

Hier findest du alle Methoden, die die Klasse Kreis zur


Verfügung stellt. Wenn du die Methode sichtbarMachen aufrufst,
dann erscheint auch ein Kreis auf dem Bildschirm und zwar in
einem speziellen Fenster, welches zur Klasse Leinwand gehört.

Aus dem Kontextmenü von kreis1 heraus kannst du jetzt


weitere Methoden aufrufen und damit z.B. den Kreis
horizontal bzw. vertikal verschieben. Manche dieser
Methoden, z.B. horizontalBewegen erwarten eine Eingabe.

Hier gibst du eine Zahl ein z.B. 50, worauf der kreis1 sich
um 50 Pixel horizontal verschiebt.

Etwas aufpassen musst du, wenn du die Methode


farbeAendern aufrufst, hier erwartet der kreis1 keine Zahl,
sondern einen Text der die Farbe angibt.

Dieser Text muss in Anführungsstriche gesetzt werden


und es stehen auch nur die im Dialogfenster angegebenen
Farben zur Verfügung.

Eine Methode kann mehr als nur einen Parameter besitzen.

Die Methode groesseAendern des Klasse Dreieck z.B.


erwartet die Angabe von zwei Parametern, nämlich Höhe
und Breite.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 -7- Hansa-Gymnasium

Datentypen in Java
Ein Datentype beschreibt die Art der Information, die Java z.B. als Parameter einer Methode
erwartet. Viele der Methoden von Kreis erwarten Zahlen als Parameter, der zugehörige Datentyp
heißt in Java int, was eine Abkürzung von integer, dem englischen Begriff für ganze Zahl ist.
Die Methode farbeAendern erwartet einen Text, eine Zeichenkette. Der zugehörige Datentyp heißt
in Java String. Strings oder Zeichenketten musst du generell in Anführungsstriche setzen.

Mehrere Instanzen
Bisher hast du nur mit einem einzigen Objekt gearbeitet,
einer Instanz der Klasse Kreis. Du kannst beliebig viele
Instanzen der gleichen Klasse erzeugen, aber auch
Instanzen verschiedener Klassen gleichzeitig. Bei
verschiedenen Instanzen der gleichen Klasse musst du
aber unbedingt darauf achten, dass sie unterschiedliche
Positionen besitzen, sonst kannst du sie im
Leinwandfenster nicht unterscheiden.

Zu diesem Projekt könnte z.B. die folgende Leinwand passen.

Aufgabe 1:
a) Erzeuge mit BlueJ und den Klassen Kreis, Quadrat und
Dreieck interaktiv eine Abbildung, die ein einfaches Haus mit
einer Sonne darstellt.
b) Versuche dabei dir die einzelnen Schritte bzw.
Methodenaufrufe so zu merken, dass du eine erneute
Darstellung des gleichen Bildes möglichst direkt erzeugen
könntest.
c) Falls du genügend Zeit zur Verfügung hast kannst du die
Zeichnung noch um weitere Elemente, wie z.B.
Tannenbäume ergänzen.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 -8- Hansa-Gymnasium

Zustand von Objekten


Bei der Arbeit mit mehreren Objekten, vor allem bei der exakten Positionierung, kann es immer
wieder vorkommen, dass Angaben über einzelne Objekte benötigt, z.B. ihre Größe oder ihre
Position. Die Werte wie Position, Farbe, Durchmesser, die ein Objekt zu einem Zeitpunkt besitzt
bezeichnet man als seinen Zustand.
Der Zustand eines Objektes lässt sich mit BlueJ relativ einfach ermitteln bzw. inspizieren. Im
Kontextmenü jedes Objektes steht dir der Menüpunkt Inspizieren zur Verfügung.

Der Zustand eines Objektes der Klasse Kreis lässt sich


durch die angegebenen fünf Datenfelder beschreiben, die
hier für die Instanz kreis1 zu sehen sind. Jede Instanz der
Klasse Kreis verfügt über die gleichen Datenfelder, aber
die Werte unterscheiden sich normalerweise von Instanz
zu Instanz. Andererseits können sich aber zwei Instanzen
der Klasse Kreis auch nur in diesen Datenfeldern
unterscheiden.

Klassen können Klassen benutzen


Ein Problem im Zusammenhang mit der Aufgabe 1 besteht
darin, dass sich das Ergebnis nicht speichern lässt, die
einzelnen Methodenaufrufe erfolgen interaktiv. Aber auch
dieses Problem lässt sich relativ einfach lösen.
Schließe das Projekt Figuren (Projekt -> Schließen) und
öffne das Projekt Zeichnung (Projekt -> Projekt öffnen...
-> Zeichnung), das sich im gleichen Verzeichnis befinden
sollte.
Hier findest du eine neue Klasse Zeichnung, die die
Klassen Kreis, Quadrat und Dreieck benutzt, wie die Pfeile
symbolisieren.

Erzeuge die eine Instanz der Klasse Zeichnung (rechte


Maustaste -> new Zeichnung()), wobei der Name der
Instanz keine Rolle spielt, du also die Vorgabe zeichnung1
übernehmen kannst.
Von dem soeben erzeugten Objekt ist erst einmal nichts zu
sehen, da es sich nicht automatisch zeichnet. Klicke mit
der rechten Maustaste auf das Objekt in der Objektleiste
und rufe die Methode zeichne auf.
Es ergibt sich das gleiche Bild, das du bei Aufgabe 1
interaktiv erzeugen solltest. Die Schritte, die du zur
Lösung von Aufgabe 1 durchgeführt hast müssen sich als
in Zeichnung wiederfinden.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 -9- Hansa-Gymnasium

Rufe jetzt das Kontextmenü der Klasse


Zeichnung auf, nicht des Objektes zeichnung1
und wähle dort den Menüpunkt Bearbeiten,
dann öffnet sich ein Editor mit dem Quelltext
der Klasse Zeichnung.
Sollten bei dir keine Zeilennummern angezeigt
werden, so kannst du dies im Menü des
Editors unter Optionen -> Einstellungen ->
Zeilennummern anzeigen ändern.

Aufgabe 2
Verändere den Quelltext von Zeichnung so, dass die Sonne nicht mehr gelb, sondern rot ist. Dazu
musst du im Quelltext die Zeile suchen, in der die Farbe der Sonne geändert wird.

Aufgabe 3
a) Erweitere den Quelltext von Zeichnung um ein weiteres Objekt, einen Mond. Der Mond soll
etwas kleiner sein als die Sonne und links vom Dach erscheinen.
b) Die Klasse Zeichnung kennt die Methoden inSchwarzWeissAendern und inFarbeAendern. Achte
darauf, dass diese Methoden auch den Mond beeinflussen.
c) Falls du noch Zeit hast kannst du deine Zeichnung um einen Tannenbaum erweitern, der
unterhalb der Sonne neben dem Haus stehen kann.

Aufgabe 4 (anspruchsvoller)
Der Mond aus Aufgabe 3 soll nach dem Zeichnen langsam untergehen.
a) Die Klasse Kreis stellt die Methoden langsamHorizontalBewegen und langsamVertikalBewegen
zur Verfügung, die du innerhalb von zeichne benutzen kannst.
b) Schreibe eine extra Methode monduntergang, die von der Methode zeichne getrennt ist. Man soll
also mittels zeichne das Bild aufbauen und dann mit monduntergang den Mond untergehen lassen.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 10 - Hansa-Gymnasium

4. Beziehungen zwischen Klassen


Bisher ging es hauptsächlich um den Unterschied zwischen Klassen und Objekten. Im vorliegenden
Abschnitt wird es hauptsächlich um die Beziehungen zwischen einzelnen Klassen gehen. Hier
werden dann so wichtige Begriffe wie Vererbung und Aggregation.

Öffne zum Einstieg das Projekt MoebelAnfang aus dem


Verzeichnis Abschnitt4. Das Projekt ähnelt dem
Einstiegsbeispiel Figuren, von daher dürfte der
Einarbeitungsaufwand gering sein. Das Projekt beinhaltet
wieder eine Leinwand-Klasse und die Klassen Stuhl und
Tisch.

Sowohl Tisch, als auch Stuhl verfügen über eine Methode dreheAuf,
über die die Orientierung der Möbelstücke verändert werden kann.
Der Winkel wird hierbei im Gradmass angegeben.

In der folgenden Aufgabe sollst du eine eigene Klasse erstellen. Dazu sind ein paar Informationen
zu Java-Klassen notwendig. Bei einer Java-Klasse müssen Dateiname und Klassenname
übereinstimmen. Eine Klasse Einrichtung muss also unter dem Dateinamen Einrichtung.java
abgespeichert sein, wobei auch die Gross-/Kleinschreibung wichtig ist. Jede Java-Klasse verfügt
über einen Konstruktor, der dazu dient Voreinstellungen vorzunehmen. Der Konstruktor darf ruhig
leer sein, muss aber so heissen, wie die Klasse.
public Einrichtung()
{
// nichts zu tun hier, alle Exemplarvariablen werden automatisch
// mit null initialisiert
}
Java führt bei leerem Konstruktor automatisch einige Initialisierungen durch. Oftmals wird man
aber im Konstruktor auch eigene Einstellungen vornehmen:
public Tisch()
{
xPosition = 120;
yPosition = 150;
orientierung = 0;
farbe = "rot";
istSichtbar = false;
breite = 120;
tiefe = 100;
}
Einem Konstruktor kann man auch Parameter übergeben, wie einer normalen Methode. Das wird in
einem späteren Abschnitt eine Rolle spielen.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 11 - Hansa-Gymnasium

Aufgabe5
Erstelle mit dem Projekt MoebelAnfang eine kleine
Sitzgruppe, zuerst interaktiv und dann, indem du eine
zusätzliche Klasse Einrichtung einführst, die die
Sitzgruppe darstellt. Du kannst dich bei der Erstellung an
der Klasse Zeichnung aus Abschnitt 3 orientieren.

Aggregation und Komposition


Bei der Objektorientierung Modellierung ist es wichtig sich deutlich zu machen, in welcher
Beziehung die verwendeten Klassen zueinander stehen. Das Verhältnis zwischen Einrichtung und
Tisch bzw. Stuhl ist eine hat-Beziehung, die man in diesem Fall als Aggregation bezeichnet. Die
Einrichtung hat einen Tisch und die Einrichtung hat Stühle. Man könnte auch sagen, die
Einrichtung besteht aus Tisch und Stühlen.

Für die Verwendung des Begriffes Aggregation ist es wichtig, dass die benutzten Klassen auch
unabhängig von der benutzenden Klasse existenzfähig sind. Falls diese Unabhängigkeit nicht
gegeben ist spricht man von einer Komposition. Ein Tisch hat Tischbeine, diese würde man
normalerweise nicht als vom Tisch unabhängig existenzfähig betrachten. Wenn ich den Tisch
wegwerfe, dann normalerweise auch seine Beine.
Ein weiteres Merkmal der Aggregation ist auch dass das Aggregat auch zeitweise ohne Teile sein
darf, eine Einrichtung ohne Tisch und Stuhl ist denkbar, ein Tisch ohne Beine aber nicht.

Aggregation und Komposition gehören beide zu den Assoziationen. BlueJ stellt Assoziationen
durch Pfeile zwischen den Klassen dar, unterscheidet aber nicht zwischen Aggregation und
Komposition.

Weitere Möbelklassen
Eine Einrichtung, die nur aus Tischen und Stühlen besteht ist relativ langweilig, deshalb soll das
Programm im nächsten Schritt um weitere Möbelklassen erweitert werden.

Aufgabe 6
Schreibe die Möbelklassen Bett, Sofa und Schrankelement, orientiere dich bei der Darstellung an
den Normzeichen für Möbel von Abschnitt 1.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 12 - Hansa-Gymnasium

Grafikbefehle in Java

Die Lösung der Aufgabe 6 ist solange nicht besonders schwierig, wie man bei Objekten bleibt, die
sich aus Linienzügen zeichnen lassen. Die Möbelstücke unterscheiden sich vor allem in der
Methode gibAktuelleFigur(). Für den Stuhl hat die Methode folgenden Inhalt:

private Shape gibAktuelleFigur()


{
GeneralPath stuhl = new GeneralPath();
stuhl.moveTo(xPosition , yPosition);
stuhl.lineTo(xPosition+breite, yPosition);
stuhl.lineTo(xPosition+breite+3, yPosition+tiefe);
stuhl.lineTo(xPosition-3 , yPosition+tiefe);
stuhl.lineTo(xPosition , yPosition );
//Das ist die Umrandung. Das Stuhl bekommt noch eine Lehne
stuhl.moveTo(xPosition , yPosition + 5 );
stuhl.lineTo(xPosition + breite , yPosition + 5);

AffineTransform t1 = new AffineTransform();


t1.rotate(Math.toRadians(orientierung),gibMitteX(),gibMitteY());

return t1.createTransformedShape(stuhl);
}

Zentrale Komponente hier ist GeneralPath, was man als Zeichenanweisung interpretieren kann.
Hier werden quasi die Anweisungen bzw. Arbeitsschritte gespeichert, die man zum Zeichen des
Objektes benötigt. Benutzt werden hier zum Zeichnen die Methoden moveTo() und lineTo(). Die
erste Methode verschiebt die Position des Zeichenstiftes ohne eine Spur zu hinterlassen. Die zweite
Methode hinterlässt eine Spur.

Die letzten drei Zeilen der Methode definieren eine Transformation, konkret eine Drehung der
Zeichnung um ihren Mittelpunkt.

Mit diesen Informationen sollten sich Möbelstücke wie Bett, Schrank und Sofa zeichnen lassen.
Etwas schwieriger wird es, wenn man abgerundete Möbelstücke, wie Klavier oder Badewanne
zeichnen möchte. Hier benötigt man weitere Informationen.
Java ist eine sehr gut dokumentierte Sprache, die Dokumentation wird automatisch aus
Kommentaren im Quelltext erzeugt werden.

In BlueJ findet sich unter Hilfe der


Menüpunkt Java
Klassenbibliotheken, über den man
einen Web-Browser mit der
Dokumentation von Sun aufrufen
kann.

Welche Webseiten hierbei geladen


werden kann man ggf. unter
Werkzeuge ● Einstellungen ●
Diverses festlegen. Bei meiner
BlueJ-Version 2.2.1 ist das die
Adresse:
http://java.sun.com/j2se/1.5/docs/api/index.html
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 13 - Hansa-Gymnasium

Die Seite besteht aus drei Frames.

Java besteht aus mehreren Paketen, z.B. dem Paket java.awt.geom mit Grafikfunktionen. Klick man
im Frame links oben auf java.awt.geom, so werden im Frame direkt darunter alle Klassen angezeigt.
Klickt man hier z.B. auf die Klasse GeneralPath, so erscheint im großen Frame die zugehörige
Dokumentation mit allen Methoden dieser Klasse.
Hier finden sich dann z.B. auch moveTo() und LineTo() mit relativ abstrakten Beschreibungen.
Recht mächtig sind hier auch die Methoden quadTo() und curveTo(), die die Angabe von zwei bzw.
drei Punkten erwarten. Die Methode quadTo() verbindet den aktuellen Punkt mit dem zweiten
Punkt über eine Kurve, deren Krümmung mit dem ersten angegebenen Punkt bestimmt wird.
Das folgende Listing erzeugt einen Kreisbogen, um den herum ein
Quadrat gezeichnet ist.
private Shape gibAktuelleFigur()
{
GeneralPath Test = new GeneralPath();
Test.moveTo(xPosition , yPosition);
Test.lineTo(xPosition+breite, yPosition);
Test.lineTo(xPosition+breite, yPosition+tiefe);
Test.lineTo(xPosition , yPosition+tiefe);
Test.lineTo(xPosition , yPosition);

Test.quadTo(xPosition, yPosition+tiefe, xPosition+breite, yPosition+tiefe);

AffineTransform t1 = new AffineTransform();


t1.rotate(Math.toRadians(orientierung),gibMitteX(),gibMitteY());

return t1.createTransformedShape(Test);
}
Die Methode curveTo() arbeitet entsprechend, nur dass hier mit zwei Hilfspunkten gearbeitet wird,
die die Darstellung von S-förmigen Kurven erlauben.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 14 - Hansa-Gymnasium

Vererbung
Beim Bearbeiten der Aufgabe 6 müsste dir aufgefallen sein, dass du mehrfach gleiche bzw. sehr
ähnliche Codezeilen schreiben musst. Derartige Redundanzen sollte man in der Programmierung
unbedingt vermeiden. Jede deiner Möbelklassen verfügt z.B. über die Methode zeige:
public void zeige()
{
istSichtbar = true;
zeichne();
}
Diese Methode ist vollkommen unabhängig von der konkreten Möbelklasse.
Eine Möglichkeit die Redundanzen zu vermeiden besteht darin eine sehr allgemeine Klasse
Moebelstueck zu definieren, von der die konkreten Möbelstücke dann erben.
import java.awt.Shape;

/**
* Ein allgemeines Möbelstück, als Grundlage für Vererbung.
*
* @author Java-MS Groupies
* hier Uwe Debacher
* nach Vorlagen von Michael Kölling und David J. Barnes und Axel Schmolitzky
* @version 1.1 (23.2.04)
*/
abstract public class Moebelstueck
{
public int xPosition;
public int yPosition;
public int orientierung;
public String farbe;
public boolean istSichtbar;

/**
* Erzeuge ein Moebelstueck mit einer Standardfarbe an einer
* Standardposition.
*/
public Moebelstueck()
{
xPosition = 160;
yPosition = 80;
farbe = "blau";
orientierung = 0;
istSichtbar = false;
}

/**
* Berechnet das zu zeichnende Shape anhand der gegebenen Daten
* [ Zum Anzeigen der Attributwerte über Inspect muss hier die Sichtbarkeit
* auf public gesetzt werden. ]
*/
abstract public Shape gibAktuelleFigur();

/**
* Mache dieses Objekt sichtbar. Wenn es bereits sichtbar ist, tue
* nichts.
*/
public void zeige()
{
istSichtbar = true;
zeichne();
}

/**
* Mache dieses Objekt unsichtbar. Wenn es bereits unsichtbar ist, tue
* nichts.
*/
public void verberge()
{
loesche();
istSichtbar = false;
}
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 15 - Hansa-Gymnasium

/**
* Drehe auf den angegebenen Winkel
*/
public void dreheAuf(int neuerWinkel)
{
loesche();
orientierung = neuerWinkel;
zeichne();
}

/**
* Bewege dieses Objekt horizontal um 'entfernung' Bildschirmpunkte.
*/
public void bewegeHorizontal(int entfernung)
{
loesche();
xPosition += entfernung;
zeichne();
}

/**
* Bewege dieses objekt vertikal um 'entfernung' Bildschirmpunkte.
*/
public void bewegeVertikal(int entfernung)
{
loesche();
yPosition += entfernung;
zeichne();
}

/**
* Ändere die Farbe dieses Objektes in 'neueFarbe'.
* Gültige Angaben sind "rot", "gelb", "blau", "gruen",
* "lila" und "schwarz".
*/
public void aendereFarbe(String neueFarbe)
{
farbe = neueFarbe;
zeichne();
}

/*
* Zeichne dieses Objekt mit seinen aktuellen Werten auf den Bildschirm.
*/
private void zeichne()
{
if (istSichtbar)
{
Shape figur = gibAktuelleFigur();
Leinwand leinwand = Leinwand.gibLeinwand();
leinwand.zeichne (
this,
farbe,
figur);
leinwand.warte(10);
}
}

/*
* Lösche dieses Objekt vom Bildschirm.
*/
private void loesche()
{
if (istSichtbar)
{
Leinwand leinwand = Leinwand.gibLeinwand();
leinwand.entferne(this);
}
}
}
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 16 - Hansa-Gymnasium

Von dieser Klasse erben dann die konkreten Möbelklassen, was zu deutlich übersichtlicheren
Quelltexten führt.
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.Graphics2D;

/**
* Ein Tisch, der manipuliert werden kann und sich selbst auf einer Leinwand zeichnet.
*
* @author Java-MS Groupies
* hier claus albowski
* nach einer Vorlage von Uwe Debacher,
* Michael Kölling und David J. Barnes und Axel Schmolitzky
* @version 1.1 (8.2.04)
*/
public class Tisch extends Moebelstueck
{
private int xPosition;
private int yPosition;
private int orientierung;
private String farbe;
private boolean istSichtbar;
private int breite;
private int tiefe;

/**
* Erzeuge einen neuen Tisch mit einer Standardfarbe an einer
* Standardposition.
*/
public Tisch()
{
breite = 120;
tiefe = 100;
}

/**
* Berechnet das zu zeichnende Shape anhand der gegebenen Daten
* [ Zum Anzeigen der Attributwerte über Inspect muss hier die Sichtbarkeit
* auf public gesetzt werden. ]
*/
public Shape gibAktuelleFigur()
{
Shape tisch = new Ellipse2D.Double(xPosition , yPosition, breite, tiefe);

AffineTransform t1 = new AffineTransform();


t1.rotate(Math.toRadians(orientierung),gibMitteX(),gibMitteY());

return t1.createTransformedShape(tisch);
}

/**
* Hole die X-Koordinate des Mittelpunktes
* [ Hilfsfunktion für das Drehen. ]
*/
private int gibMitteX()
{
return xPosition+breite/2;
}

/**
* Hole die Y-Koordinate des Mittelpunktes
* [ Hilfsfunktion für das Drehen. ]
*/
private int gibMitteY()
{
return yPosition+tiefe/2;
}

}
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 17 - Hansa-Gymnasium

5. Sammlungen von Objekten


An vielen Stellen werden Sammlungen von gleichartigen Objekten benötigt. Eine Möglichkeit wäre
z.B. die Einführung eines Objektes Sitzgruppe, welches selber aus einem Tisch und vier Stühlen
bestehen könnte, wie in Aufgabe 5.

Idealerweise möchte man eine derartige Sammlung zu Laufzeit des Programms erstellen und
erweitern können, was bei dem bisherigen Ansatz nicht möglich ist.

Java bietet für derartige Situationen mehrere Lösungsmöglichkeiten an.

Aufgabe 7
Öffne das Projekt Notizbuch1 aus dem Verzeichnis Abschnitt5. Das Projekt besteht nur aus einer
einzigen Klasse Notizbuch, die einzelne Einträge verwalten kann. Arbeite mit dieser Klasse gib u.a.
mehrere Notizen ein.
Analysiere die Funktionsweise der Sammlung, die Notizbuch benutzt.
import java.util.ArrayList;

/**
* Eine Klasse zur Verwaltung von beliebig langen Notizlisten.
* Notizen sind nummeriert, um durch einen Benutzer referenziert
* werden zu können.
* In dieser Version starten die Notiznummern bei 0.
*
* @author David J. Barnes and Michael Kolling.
* @version 2003.04.15
*/
public class Notizbuch
{
// Speicher für eine beliebige Anzahl an Notizen.
private ArrayList notizen;
/**
* Führe die Initialisierungen durch, die für ein Notizbuch
* notwendig sind.
*/
public Notizbuch()
{
notizen = new ArrayList();
}
/**
* Speichere eine neue Notiz in diesem Notizbuch.
* @param notiz die zu speichernde Notiz.
*/
public void speichereNotiz(String notiz)
{
notizen.add(notiz);
}
/**
* @return die Anzahl der Notizen in diesem Notizbuch.
*/
public int anzahlNotizen()
{
return notizen.size();
}
/**
* Zeige eine Notiz.
* @param notiznummer die Nummer der Notiz, die gezeigt werden soll.
*/
public void zeigeNotiz(int notiznummer)
{
if(notiznummer < 0) {
// Keine gültige Nummer, nichts zu tun.
}
else if(notiznummer < anzahlNotizen()) {
// Die Nummer ist gültig, wir können die Notiz ausgeben.
System.out.println(notizen.get(notiznummer));
}
else {
// Keine gültige Nummer, nichts zu tun.
}
}
}
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 18 - Hansa-Gymnasium

Aufgabe 8
Erweitere das Projekt Notizbuch so, dass einzelne Notizen auch gelöscht werden können, dafür
steht in einer ArrayList die Methode remove(int nummer) zur Verfügung.

Iteration
Will man alle Notizen des Notizbuches ausgeben, so benötigt man eine Wiederholstruktur oder
Schleifenstruktur. Java kennt dafür mehrere Konstrukte, die hier jeweils gleich am konkreten
Beispiel dargestellt werden.

Die while-Schleife
Sehr einfach zu handhaben ist die while-Schleife. Hier wird ein Programmteil solange ausgeführt,
wie eine Bedingung wahr ist.

while (Schleifenbedingung) {
Schleifenrumpf
}

Konkret bezogen auf das Notizbuch ergäbe sich folgendes Listing.

int index = 0;
while(index < notizen.size()) {
System.out.println(notizen.get(index));
index++;
}

Iteratoren
Bei der Ausgabe der Notizen spielen die Nummern der Einträge eigentlich keine grosse Rolle. Es
gibt Sammlungen, bei denen Nummern auch gar nicht vorhanden sind. Da ist ein Konstrukt
übersichtlicher, mit dem man formulieren kann, wenn es einen weiteren Datensatz gibt, dann gib
den nächsten Datensatz aus. Genau so arbeitet ein Iterator.
Jede Sammlung, wie in diesem Fall die ArrayList, verfügt über ein Iterator-Objekt. Dieses Iterator-
Objekt kennt dann die Methoden hasNext() und next().

Iterator it = notiz.iterator();
while(it.hasNext()) {
System.out.printeln(it.next()),
}

Die for-Schleife
Wenn man genau weiss, wie oft eine Iteration durchzuführen ist, dann kann man auch mit der for-
Schleife arbeiten, die schon in einem der ersten Beispiele auftauchte.

for(Initialisierung; Bedingung; Aktion nach dem Rumpf) {


Schleifenrumpf
}
Bezogen auf das Notizbuch sieht das folgendermassen aus:

for (int index; index<notizen.size(); index=index+1)


System.out.printeln(notizen.get(index));
}

Welche der beiden Schleifenarten man bevorzugt hängt von der Situation und auch dem
persönlichen Geschmack ab. Im Zweifelsfall sollte man der while-Schleife den Vorzug geben.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 19 - Hansa-Gymnasium

Ein Hinweis noch zum Umgang noch mit der Konsole von BlueJ. Ausgaben wie
System.out.printeln(it.next())

erfolgen auf die Systemkonsole des jeweiligen Betriebssystems. Bei Windos ist das üblicherweise
ein schwarzes Fenster das zur DOS-Shell gehört. BlueJ
fängt diese Ausgaben ab und leitet sie in ein Fenster seiner
grafischen Oberfläche um.
Dieses Fenster benimmt sich aber ähnlich wie das DOS-
Fenster, es sammeln sich vor allem die Ausgaben
unterschiedlicher Programmdurchläufe an, was schnell
unübersichtlich wird. Daher bietet BlueJ für dieses Fenster
auch eine Löschfunktion an.
Über Optionen -> Konsole löschen steht diese Funktion
jederzeit zur Verfügung.

Eine mögliche Lösung für Aufgabe 8 könnte dann folgendermaßen aussehen:


/**
* Entferne die Notiz mit der angegebenen Nummer aus
* diesem Notizbuch, wenn sie existiert.
* @param notiznummer die Nummer der zu entfernenden Notiz.
*/
public void entferneNotiz(int notiznummer)
{
if(notiznummer < 0) {
// Keine gültige Nummer, nichts zu tun.
}
else if(notiznummer < anzahlNotizen()) {
// Die Notiznummer ist gültig.
notizen.remove(notiznummer);
}
else {
// Keine gültige Nummer, nichts zu tun.
}
}

Aufgabe 9
Erweitere das Projekt Notizbuch um eine Methode zum Anzeigen aller Einträge.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 20 - Hansa-Gymnasium

6. Polymorphie
Die Aufgabe 9 dürfte nun nicht mehr besonders kompliziert sein, die Lösung basiert auf einer der
angesprochenen Iterationen. Interessant an der folgenden Lösung ist vor allem, dass die Methode
den gleichen Namen besitzt, wie die bereits vorhandene Methode zum Löschen eines einzelnen
Datensatzes.

/**
* Gib alle Notizen dieses Notizbuchs auf die Konsole aus.
*/
public void zeigeNotiz()
{
int index = 0;
while(index < notizen.size()) {
zeigeNotiz(index);
index++;
}
}

Java erlaubt es den gleichen Methodennamen mehrfach zu benutzen, sofern sich zumindest der
Interface-Teil der Methoden voneinander unterscheidet, dies bezeichnet man als Polymorphie
(Vielgestaltigkeit), genauer als Methoden-Polymorphie (polymorphe Variablen werden etwas später
auftauchen).

Aufgabe 10
Erweitere das Projekt Notizbuch um eine Methode zeigeNotiz(String vergleichstext).

Aufgabe 11
Erweitere das Projekt Notizbuch um die Methoden:
– entferneNotiz() zum Löschen aller Datensätze
– entferneNotiz(String vergleichstext) zum Löschen übereinstimmender Datensätze.
Die Aufgabe 10 ist auf den ersten Blick nicht besonders spannend, da unser Notizbuch nicht mehr
speichert, als auch im Vergleichstext auftaucht. Bei komplexeren Objekten könnte man aber auf
entsprechende Art nach einem Element suchen, das einen bestimmten Feldinhalt besitzt.

Bei der Lösung der Aufgabe 10 taucht ein interessantes Problem auf, nämlich die Frage, wann zwei
Strings gleich sind.

/**
* Zeige eine Notiz.
* @param Text der Notiz, die gezeigt werden soll.
*/
public void zeigeNotiz(String vergleichstext)
{
int index = 0;
while(index < notizen.size()) {
if (vergleichstext.equals(notizen.get(index))) {
zeigeNotiz(index);
}
index++;
}
}
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 21 - Hansa-Gymnasium

Der Vergleich der Strings nach dem Muster


if (vergleichstext == notizen.get(index)) ....
funktioniert nicht unbedingt. Genaugenommen wird hier nämlich überprüft, ob die beiden String-
Objekte gleich sind, was oft selbst dann nicht der Fall ist, wenn beide Objekte den gleichen Text
beinhalten. Stringobjekte sollte man daher nie auf diese Art vergleichen, sondern über die equals-
Methode eines der Objekte.
if (vergleichstext.equals(notizen.get(index))) ...

Mögliche Lösungen für Aufgabe 11 zeigt das folgende Listing.

/**
* Entfernt alle Notizen dieses Notizbuches.
*/
public void entferneNotiz()
{
notizen.clear();
}

/**
* Entfernt die Notiz mit dem angegebenen Text.
* @param Text der Notiz, die entfernt werden soll.
*/
public void entferneNotiz(String vergleichstext)
{
int index=0;
while (index<anzahlNotizen()) {
if (vergleichstext.equals(notizen.get(index))) {
entferneNotiz(index);
break;
}
}
}

Beim Löschen von Datensätzen taucht ein Problem auf. Der gesamte Rest der Liste verschiebt sich
und auch die Anzahl der Elemente verringert sich. Man muss daher sehr aufpassen, wie man
weiterarbeitet. Im vorliegenden Listing wurde hier der sicherste Weg gewählt, nämlich die Schleife
mittels break verlassen, wenn wenn ein Datensatz gelöscht wurde. Damit können keine Probleme
mit dem Index auftauchen, dafür wird aber nur der erste gefundene Datensatz gelöscht.

Das Definieren von mehreren Methoden bezeichnet man als Überladen. Die Methoden sind parallel
und unabhängig voneinander vorhanden. Sie müssen sich in ihrer Signatur, der Anzahl bzw. dem
Typ der Parameter, unterscheiden.

Eine Methode mit identischer Signatur kann man in abgeleiteten Klassen schrieben. Dann ist nur die
neue Methode zugänglich, die geerbte Methode aus der Ursprungsklasse ist dann nicht direkt
erreichbar. Dies bezeichnet man als Überschreiben.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 22 - Hansa-Gymnasium

7. Sitzgruppe
Im nächsten Schritt soll unser Möbelprojekt um ein zusammengesetztes Objekt erweitert werden,
eine Sitzgruppe, die z.B. aus einem Tisch und vier Stühlen besteht, analog zu Aufgabe 5.

Aufgabe 12:
Erstelle eine Klassendiagramm für das Möbelprojekt mit Sitzgruppe

Wenn man etwas über die Aufgabenstellung nachdenkt, dann kommt man schnell zu dem Schluss,
dass die Sitzgruppe selber ein Möbelstück sein muss, wie Tisch und Stuhl auch. Sie soll z.B. als
Ganzes verschoben werden können. Da sie auf der anderen Seite auch einen Tisch und vier Stühle
hat ergibt sich das folgende Klassendiagramm.

Der einfachste Ansatz zur Lösung dieser Aufgabe besteht darin Tisch und Stuhl als
Klassenvariablen einzurichten:
public class Sitzgruppe extends Moebelstueck
{
private int breite;
private int tiefe;
private Tisch tisch;
private Stuhl stuhl1;
private Stuhl stuhl2;
private Stuhl stuhl3;
private Stuhl stuhl4;
...

Damit ist dann an vielen Stellen das weitere Vorgehen klar, z.B. beim Konstruktor.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 23 - Hansa-Gymnasium

/**
* Konstruktor für Objekte der Klasse Sitzgruppe
*/
public Sitzgruppe()
{
super();
breite=220;
tiefe=230;

tisch = new Tisch();


tisch.bewegeHorizontal(xPosition+70);
tisch.bewegeVertikal(yPosition+70);

stuhl1 = new Stuhl();


stuhl1.bewegeHorizontal(xPosition+110);
stuhl1.bewegeVertikal(yPosition+10);
stuhl1.dreheAuf(0);

stuhl2 = new Stuhl();


stuhl2.bewegeHorizontal(xPosition+10);
stuhl2.bewegeVertikal(yPosition+100);
stuhl2.dreheAuf(270);

stuhl3 = new Stuhl();


stuhl3.bewegeHorizontal(xPosition+110);
stuhl3.bewegeVertikal(yPosition+190);
stuhl3.dreheAuf(180);

stuhl4 = new Stuhl();


stuhl4.bewegeHorizontal(xPosition+210);
stuhl4.bewegeVertikal(yPosition+100);
stuhl4.dreheAuf(90);
}

Dieser Teil lässt sich kaum geschickter Gestalten, da die Positionen und Ausrichtungen der
einzelnen Komponenten vorgegeben werden müssen.

Spannender wird es, wenn es an die einzelnen Nachrichten geht. Im einfachsten Fall reagiert die
Sitzgruppe auf eine Nachricht wie zeige(), indem sie diese Nachricht an ihre einzelnen
Komponenten weitergibt.

/**
* Mache dieses Objekt sichtbar. Wenn es bereits sichtbar ist, tut
* sich nichts.
*/
public void zeige()
{
istSichtbar = true;
tisch.zeige();
stuhl1.zeige();
stuhl2.zeige();
stuhl3.zeige();
stuhl4.zeige();
}

Das funktioniert für fast alle Nachrichten entsprechend. Etwas schwieriger wird es nur für alles, was
in irgendeiner Weise mit der Drehung zusammenhängt, also auch für gibAktuelleFigur().
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 24 - Hansa-Gymnasium

Wenn wir der Sitzgruppe die Nachricht dreheAuf() schicken und die Sitzgruppe diese an ihre
Komponenten weiterreicht, dann würden nur die Komponenten innerhalb der Sitzgruppe gedreht,
nicht aber die Sitzgruppe. Auf dieses Problem werden wir später noch einmal zurück kommen.

Da wir die Methode gibAktuelleFigur() unbedingt implementieren müssen, sie war in Moebelstück
nur abstrakt erklärt, hier erst einmal ein erster Ansatz, der sich weitgehend an der Methode von
Tisch und Stuhl orientiert.

/**
* Berechnet das zu zeichnende Shape anhand der gegebenen Daten
* [ Zum Anzeigen der Attributwerte über Inspect muss hier die Sichtbarkeit
* auf public gesetzt werden. ]
*/
public Shape gibAktuelleFigur()
{
GeneralPath sitzgruppe = new GeneralPath();
sitzgruppe.append( tisch.gibAktuelleFigur(), false);
sitzgruppe.append( stuhl1.gibAktuelleFigur(), false);
sitzgruppe.append( stuhl2.gibAktuelleFigur(), false);
sitzgruppe.append( stuhl3.gibAktuelleFigur(), false);
sitzgruppe.append( stuhl4.gibAktuelleFigur(), false);

AffineTransform t1 = new AffineTransform();


t1.rotate(Math.toRadians(orientierung),gibMitteX(),gibMitteY());

return t1.createTransformedShape(sitzgruppe);
}

Aufgabe 13:
Vervollständige die Klasse Sitzgruppe, akzeptiere dabei erst einmal Probleme beim Drehen.

Hinweis:
Bei dieser Gelegenheit bietet es sich an ein kleines Designproblem aus der Klasse Moebelstuck zu
korrigieren und alle Objekte mit der Anfangsposition (0,0) zu initialisieren. Dazu müssen nur die
Werte im Konstruktor angepasst werden.

public Moebelstueck()
{
xPosition = 0;
yPosition = 0;
farbe = "blau";
orientierung = 0;
istSichtbar = false;
}

Diese Änderung erleichtert die Positionierung der Komponenten.


Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 25 - Hansa-Gymnasium

8. Optimierung der Modellierung


Beim Arbeiten an der Sitzgruppe fällt ein Design-Problem des bisherigen Projektes auf. Die
Positionierung ist bisher an zwei unterschiedlichen Stellen geregelt.
• Die Verschiebung (Translation) erfolgt über die Zeichenbefehle in gibAktuelleFigur(),
• die Drehung (Rotation) erfolgt über eine affine Transformation.

Einfacher wird es, wenn man bei Operationen über affine Transformationen regelt. Dazu sind
lediglich geringe Veränderungen an der Methode gibAktuelleFigur() notwendig.

Hier die Methode für den Stuhl:


/**
* Berechnet das zu zeichnende Shape anhand der gegebenen Daten
* [ Zum Anzeigen der Attributwerte über Inspect muss hier die Sichtbarkeit
* auf public gesetzt werden. ]
*/
public Shape gibAktuelleFigur()
{
GeneralPath stuhl = new GeneralPath();
stuhl.moveTo(0, 0);
stuhl.lineTo(0+breite, 0);
stuhl.lineTo(0+breite+3, 0+tiefe);
stuhl.lineTo(0-3 , 0+tiefe);
stuhl.lineTo(0 , 0 );
//Das ist die Umrandung. Das Stuhl bekommt noch eine Lehne
stuhl.moveTo(0 , 0 + 5 );
stuhl.lineTo(0 + breite , 0 + 5);

AffineTransform t1 = new AffineTransform();


t1.rotate(Math.toRadians(orientierung),gibMitteX(),gibMitteY());
t1.translate(xPosition, yPosition);

return t1.createTransformedShape(stuhl);
}

Der Stuhl wird hier ab der Startposition (0/0) erzeugt und erst hinterher über eine Translation
verschoben.

Die überarbeitete Methode für den Tisch sieht dann folgendermassen aus.
/**
* Berechnet das zu zeichnende Shape anhand der gegebenen Daten
* [ Zum Anzeigen der Attributwerte über Inspect muss hier die Sichtbarkeit
* auf public gesetzt werden. ]
*/
public Shape gibAktuelleFigur()
{
GeneralPath tisch = new GeneralPath();
tisch.append( new Ellipse2D.Double(0 , 0, breite, tiefe), false);

AffineTransform t1 = new AffineTransform();


t1.rotate(Math.toRadians(orientierung),gibMitteX(),gibMitteY());
t1.translate(xPosition, yPosition);

return t1.createTransformedShape(tisch);
}
Hier ist übrigens gleich eine weitere kleine Inkonsistenz beseitigt, indem auch der Tisch über einen
GeneralPath erzeugt wird.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 26 - Hansa-Gymnasium

Nach diesen Änderungen lässt sich die Klasse Sitzgruppe recht einfach formulieren. Es sind nur
ganz wenige Methoden notwendig.
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.AffineTransform;

/**
*
* @author Java-MS Groupies
* hier claus albowski
* nach einer Vorlage von Uwe Debacher,
* Michael Kölling und David J. Barnes und Axel Schmolitzky
* Bearbeitung Rudolf Wilzek
* @version 1.2 (5.5.04)
*/

public class Sitzgruppe extends Moebelstueck


{
// Instanzvariablen - ersetzen Sie das folgende Beispiel mit Ihren Variablen
private int breite;
private int tiefe;
private Tisch tisch;
private Stuhl stuhl1;
private Stuhl stuhl2;
private Stuhl stuhl3;
private Stuhl stuhl4;

/**
* Konstruktor für Objekte der Klasse Sitzgruppe
*/
public Sitzgruppe()
{
// Instanzvariable initialisieren
super();
breite=220;
tiefe=230;

tisch = new Tisch();


tisch.bewegeHorizontal(xPosition+70);
tisch.bewegeVertikal(yPosition+70);

stuhl1 = new Stuhl();


stuhl1.bewegeHorizontal(xPosition+110);
stuhl1.bewegeVertikal(yPosition+10);
stuhl1.dreheAuf(0);

stuhl2 = new Stuhl();


stuhl2.bewegeHorizontal(xPosition+10);
stuhl2.bewegeVertikal(yPosition+100);
stuhl2.dreheAuf(270);

stuhl3 = new Stuhl();


stuhl3.bewegeHorizontal(xPosition+110);
stuhl3.bewegeVertikal(yPosition+190);
stuhl3.dreheAuf(180);

stuhl4 = new Stuhl();


stuhl4.bewegeHorizontal(xPosition+210);
stuhl4.bewegeVertikal(yPosition+100);
stuhl4.dreheAuf(90);
}
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 27 - Hansa-Gymnasium

public Shape gibAktuelleFigur()


{
GeneralPath sitzgruppe = new GeneralPath();
sitzgruppe.append( tisch.gibAktuelleFigur(), false);
sitzgruppe.append( stuhl1.gibAktuelleFigur(), false);
sitzgruppe.append( stuhl2.gibAktuelleFigur(), false);
sitzgruppe.append( stuhl3.gibAktuelleFigur(), false);
sitzgruppe.append( stuhl4.gibAktuelleFigur(), false);

AffineTransform t1 = new AffineTransform();


t1.rotate(Math.toRadians(orientierung),gibMitteX(),gibMitteY());
t1.translate(xPosition, yPosition);
return t1.createTransformedShape(sitzgruppe);
}

/**
* Hole die X-Koordinate des Mittelpunktes
* [ Hilfsfunktion für das Drehen. ]
*/
private int gibMitteX()
{
return xPosition+breite/2;
}

/**
* Hole die Y-Koordinate des Mittelpunktes
* [ Hilfsfunktion für das Drehen. ]
*/
private int gibMitteY()
{
return yPosition+tiefe/2;
}
}

Nicht vermeiden lässt sich die Beschreibung der Möbelgruppe, wie sie hier im Konstruktor erfolgt.
Die restlichen Operationen lassen sich aber ganz einfach erschlagen, da alle Verschiebungen und
die Drehung über gibAktuelleFigur() erledigt werden.
Hier wird zuerst ein Gesamt-Shape erzeugt, das sich aus den einzelnen Shapes zusammen setzt.
Dieses Gesamt-Shape wird dann den Transformationen unterzogen.

Dadurch ist auch gewährleistet, dass sich die Sitzgruppe um einen einheitlichen Drehpunkt dreht
und nicht die Einzel-Objekte jeweils um ihren Mittelpunkt, was nicht gewünscht wäre.
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 28 - Hansa-Gymnasium

In der bisherigen Form ist der Aufbau der Sitzgruppe recht starr, wenn man z.B. die Anzahl der
Stühle variieren will, dann muss man an mehreren Stellen im Listing Änderungen vornehmen.

Deutlich flexibler wird der Ansatz, wenn man alle Objekte in einer Liste sammelt.
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;

/**
* @author Java-MS Groupies
* hier claus albowski
* nach einer Vorlage von Uwe Debacher,
* Michael Kölling und David J. Barnes und Axel Schmolitzky
* letzte Bearbeitung Uwe Debacher
* @version 1.2 (1.6.04)
*/

public class Sitzgruppe extends Moebelstueck


{
// Instanzvariablen
private int breite;
private int tiefe;
private ArrayList bestandteile;

/**
* Konstruktor für Objekte der Klasse Sitzgruppe
*/
public Sitzgruppe()
{
// Instanzvariablen initialisieren
super();
breite=220;
tiefe=230;
bestandteile = new ArrayList();
Moebelstueck hilf;

hilf = new Tisch();


hilf.bewegeHorizontal(xPosition+70);
hilf.bewegeVertikal(yPosition+70);
bestandteile.add(hilf);

hilf = new Stuhl();


hilf.bewegeHorizontal(xPosition+110);
hilf.bewegeVertikal(yPosition+10);
hilf.dreheAuf(0);
bestandteile.add(hilf);

hilf = new Stuhl();


hilf.bewegeHorizontal(xPosition+10);
hilf.bewegeVertikal(yPosition+100);
hilf.dreheAuf(270);
bestandteile.add(hilf);

hilf = new Stuhl();


hilf.bewegeHorizontal(xPosition+110);
hilf.bewegeVertikal(yPosition+190);
hilf.dreheAuf(180);
bestandteile.add(hilf);

hilf = new Stuhl();


hilf.bewegeHorizontal(xPosition+210);
hilf.bewegeVertikal(yPosition+100);
hilf.dreheAuf(90);
bestandteile.add(hilf);
}
Objektorientierte Modellierung mit BlueJ
Uwe Debacher 2008 - 29 - Hansa-Gymnasium

public Shape gibAktuelleFigur()


{
GeneralPath sitzgruppe = new GeneralPath();

for (int index=0; index<bestandteile.size(); index=index+1) {


sitzgruppe.append(( (Moebelstueck) bestandteile.get(index)).gibAktuelleFigur(), false);
}

AffineTransform t1 = new AffineTransform();


t1.rotate(Math.toRadians(orientierung),gibMitteX(),gibMitteY());
t1.translate(xPosition, yPosition);
return t1.createTransformedShape(sitzgruppe);
}

/**
* Hole die X-Koordinate des Mittelpunktes
* [ Hilfsfunktion für das Drehen. ]
*/
private int gibMitteX()
{
return xPosition+breite/2;
}

/**
* Hole die Y-Koordinate des Mittelpunktes
* [ Hilfsfunktion für das Drehen. ]
*/
private int gibMitteY()
{
return yPosition+tiefe/2;
}
}

Von der Bedienung her ist diese Lösung vollkommen identisch zur vorherigen. Lediglich beim
Inspizieren der Variablen kann man beide Lösungen voneinander unterscheiden.

Mit diesem Ansatz wird es auch möglich Möbelstücke zur Laufzeit zu einer Gruppe hinzu zu fügen.
Dazu ist lediglich die folgende neue Methode notwendig.

public void neuerBestandteil(Moebelstueck komponente)


{
bestandteile.add(komponente);
zeichne();
}

Aufgabe 14:
Erweitere das Möbelprogramm um die Möglichkeit Wände zu zeichnen. Diese Wände sollen in der
Endausbaustufe auch über Durchbrüche für Türen und Fenster verfügen.