Grundkenntnisse in der objektorientierten Programmierung sind heutzutage für propädeutische Informatikfächerkombinationen sowie für eine Vielzahl beruflicher Ausbildungen unabkömmlich. Diese Hausarbeit der Fachdidaktik Informatik widmet sich der Erstellung geeigneter Unterrichtmaterlien um eine kompakte Einführung in die wichtigsten Themengebiete der objektorientierten Programmierung zu vermitteln. Als Programmiersprache wurde Java verwendet, die behandelten objektorientierten Funktionalitäten eignen sich auch für den unkomplizierten Transfer auf andere Programmiersprachen. Alle Kurzaufgaben sind darauf ausgerichtet die Teilnehmer auf die Entwicklung eines einfachen Grafikprogramms vorzubereiten.
Inhalt
1 Objekte und Klassen
1.1 Grundlegender Modellierungsansatz
1.1.1 Praxisszenario
1.2 Elemente einer Klasse
1.2.1 Methoden
1.2.2 Zugriffsmodifikatoren
1.2.3 Eigenschaften
1.2.4 Konstruktoren
1.2.5 Praxisaufgaben
2 Vererbung
2.1 Aufbau einer einfachen Klassenhierarchie
2.1.1 Praxisbezug
2.1.2 Praxisaufgaben
3 Einführung in Collections und Vererbung
3.1 Die KlasseArrayList
3.2 Überblick zu den wichtigsten Interfaces und Klassen im Collectionsframework
4 Einführung in die GUI Entwicklung mit dem AWT
4.1 Ein FenstermitTextausgabe
4.2 Layoutmanager
4.2.1 Praxisaufgaben
4.3 Komponenten und Container
4.4 Ereignisbehandlung
4.4.1 Weitere wichtige Ereignissezurgrundlegenden Benutzerinteraktion
4.4.2 Auswahl aus einer Liste
4.4.3 Mausereignisse und Schließen von Fenstern
4.4.4 Praxisaufgaben
4.5 Ein Fenster mit grafischer Ausgabe
4.6 Eine benutzerdefinierte Komponente
4.6.1 Praxisaufgaben
5 Lösungen
5.1 Aufgabe 3 :
5.2 Aufgabe 4 :
5.3 Aufgabe 5 :
5.4 Aufgabe 6 :
5.5 Aufgabe 7 :
5.6 Aufgabe 9 :
5.7 Aufgabe 10 :
5.8 Aufgabe13
5.9 Aufgabe 14
5.10Aufgabe 16 :
5.11 Aufgabe 17 :
5.12 Aufgabe 22 :
1 Objekte und Klassen
1.1 Grundlegender Modellierungsansatz
Die Realität die uns Menschen umgibt, lässt sich grundlegend in zwei Bemessungskategorien aufteilen : Raum und Zeit. Wie in vielen Bereichen soll Technik dazu dienlich sein, Vorgänge aus der menschlichen Umwelt, kontrollierbar und einfacher bzw. rationalisierbar zu machen, so dass der Alltag leichter bewältigt werden kann und sich gesellschaftlich höhere Standards etablieren können. Betrachtet man die technische Entwicklung einer Vielzahl von Maschinen und Werkzeugen, so kann festgestellt werden, dass eine stetige Erhöhung der Funktionalität und eine Verbesserung des Zusammenspiels stattfindet. Genau das gleiche kann man auch in der Softwaretechnik beobachten und deren Anwendungsmöglichkeiten sind je nach Vielseitigkeit der Ausprägungen in den jeweiligen Subdisziplinen der Bereiche Wissenschaft, Ingenieurswesen, Wirtschaft und Organisation sehr vielseitig. Agiert man nun als Anwender oder Entwickler mit Softwaresystemen, so kann man feststellen, dass Software immer wieder einen Teil der Realität abbildet, der vereinfacht bedient, sicherer oder günstiger gestaltet werden soll.
Genauso wie wir unsere Sprache zur Beschreibung von beliebigen Sachverhalten nutzen können, ist das auch zu einem sehr hohen Grad mit Software möglich. Untersuchen wir einfache Sätze, stellen wir fest, dass wir einen großen Anteil von Aussagen mit Nomen, Verben und Adjektive beschreiben können. Während Nomen oftmals konkrete vorstellbare Objekte definieren (z.B. Haus, Auto, etc.) beschreiben Verben häufig Vorgänge (z.B. öffnen, fahren, etc.). Vorgänge sind oftmals in der Realität durch die Einhaltung bestimmter Reihenfolgen von Aktivitäten gekennzeichnet und benötigen immer eine bestimmte Zeit. Eigenschaften, in der Grammatik auch als Adjektive bekannt, beschreiben wiederum Details zu Objekten oder Vorgängen/Prozessen z.B. « Das Haus ist grün » oder « Das Auto fährt langsam ».
Aufgabe 1; Bitten Sie Ihren Gruppenpartner um zwei kurze Aussagesätze, notieren Sie diese und heben Sie anschließend die Nomen, Verben und Adjektive farblich hervor !
Sollen nun diese Aussagen als Objekte die einen bestimmten Zustand haben abgebildet werden, stellt man fest, dass jene von ihrer Natur her komplexer sind als die Standardarddatentypen (primitive oder auch integrierte Datentypen genannt), welche die Programmiersprache Java von Hause aus mitbringt (z.B. int, double, booelan etc.). Ähnlich wie man die primitive Datentypen deklarieren und initialisieren muss, ist die Vorgehensweise in der objektorientierten Programmierung identisch. Nur ist es von Anfang an wichtig zu unterscheiden zwischen der Möglichkeit benutzerdefinierte Datentypen (Klassen) zu erstellen (definieren) oder diese zu verwenden (vgl. deklarieren und initialisieren). Im zweiten und einfacheren Fall, den wir zuerst betrachten wollen, wird dann eben einer Objektvariable ein oder mehrere Werte zugewiesen, die deren Zustand beschreiben.
Daher soll nun an dieser Stelle folgende Objektdiagrammnotation eingeführt werden : Objektname : Datentyp
Attributname = Wert
Abbildung in dieser Leseprobe nicht enthalten
1.Abbildung
Aufgabe 2 ; Fertigen Sie zwei Objektdiagramme zu Aufgabe 1 an!
1.1.1 Praxisszenario
Für einen Autohändler möchten wir eine einfache Schnittstelle zu einer Fahrstuhlapplikation aufbauen die eine 2D Übersicht in Form einer Bestandskarte zur weiteren Navigation bietet. Auch soll es später möglich sein per Spracheingabe z.B. einen Markennamen zu nennen und Fahrzeuge und Stockwerke werden farbig hervorgehoben. Der Einfachheitshalber werden an dieser Stelle Beschreibungen zum Ein- und Ausgangsformat der Daten noch ignoriert.
Da der Autohändler seine Fahrzeuge in einem mehrstöckigen Turm ausgestellt hat, sollen schwere, teure und vieltürige Modelle in den unteren Stockwerken zu finden sein und die günstigeren in den oberen lichtdurchlässigen und begrünten Etagen.
Da ein Fahrzeug offensichtlich in dieser Anwendung öfters verwendet werden soll, bietet es sich an, einen neuen « benutzerdefinierten » Datentyp, auch Klasse genannt, zu entwerfen. Die Vorgehensweise ist dabei im Vergleich zum grundlegenden Modellierungsansatz (s.a. Kap. 1.1) sehr ähnlich. Zuerst wird gemäß der Anforderungsbeschreibung (s.o.), also dem kleinen Lastenheft, das zentrale Subjekt, eben hier Fahrzeug ermittelt, und die Eigenschaften ausfindig gemacht die für die Zustandsbeschreibung der späteren Objekte notwendig sind. Nach Rückfragen des Projektleiters beim Kunden, konnte noch eine weitere verdeckte Anforderung ermittelt werden ; der Kunde plant auch zu einem späteren Zeitpunkt die Erweiterung des Sortiments um Zweiräder.
1.2 Elemente einer Klasse
1.2.1 Methoden
Anhand des oben gezeigten Beispiels kann auch wiederum die allgemeine Notationsvorschrift erkannt werden :
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 2
Aus dieser allgemeinen Notationsvorschrift geht bereits das nächste Klassenelement hervor : Methoden. Methoden, oder auch Funktionen in nicht objektorientierten Programmiersprachen genannt, kennzeichnen einen Codeblock mit einer eindeutigen Einsprungadresse zur Ausführung von anderen Anweisungen. Dabei können diesen Methoden Argumente zur weiteren Verarbeitung übergeben werden (vgl. Mathematik f(x) und f(4)).
Definition einer Methode :
[Zugriffsmodifikator] [static] [Rückgabetyp] MethodennameffDatentyp Argumentname] ...)
Genauso wie es Sinn macht das Variablen eine eindeutige Benennung haben, ist dies auch bei Methoden der Fall. Der eindeutige Name einer Methode ergibt sich aus dem Rückgabetyp, dem Methodennamen selbst, und der Reihenfolge der Datentypen der Parameter. Beispielsweise könnte es daher zwei unterschiedliche Methoden fahren geben : void_fahren() und void_fahren(int). Inwiefern der Rückgabetyp alleine für einen separaten Methodennamen ausreicht ist, oftmals abhängig von der Programmiersprache und der jeweiligen Compilerimplementierung, entsprechende Konventionsverstöße können zu erheblichen Portierungsproblemen führen. Ist hingegen eine Methode bereits in einer Basisklasse vorhanden, dies kann auch die implizite Basisklasse Object sein, und wird eine solche Methode vererbt, so kann diese in der Subklasse neu definiert werden, man spricht dann in diesem Fall vom überschreiben einer Methode (s.a. Kapitel Vererbung). Zu Übungszwecken werden wir häufig am Anfang die String toString() der Klasse Object überschreiben um den Status unserer Objekte in der überladenen Version der printing..) Methode ausgeben zu können. Dabei ist dann diese Methode in der jeweiligen Klassen einfach zu definieren. Zur printin() Methode des Buffers out für die Konsole gibt es eine Vielzahl von Überladungen (s.a. Dokumentation zu System.out.printin (...)), häufig kommt es jedoch auf Grund der impliziten Umwandlungen von Zeichenketten und dem Konkatenationsoperator „+“ zu einem Aufrufder Methodenversion von printin die einen String erwartet.
1.2.2 Zugriffsmodifikatoren
An obigen UML Klassendiagramm der Klasse Fahrzeug ist oftmals das Zeichen + zu erkennen. Zeichen wie +,-,# sind Abkürzungen für Zugriffsmodifikatoren : + steht für public, - für private und # für protected. Ist kein Zeichen vorhanden, so ist damit der Standardzugriffsmodifikator gemeint, welcher in der Regel in den meisten objektorientierten Programmiersprachen für einen klasseninternen Zugriff steht. public hingegen bedeutet das ein Element auch außerhalb von Klassen sichtbar ist, in Java wird ein solche Gruppierungsmöglichkeit ein Paket (engl. package) genannt. Möchte man explizit verhindern das ein Element auch außerhalb einer Klasse sichtbar ist, dann ist dieses mit private zu versehen. Häufig wird private auch für die Kapselung von Properties verwendet. Properties sind Instanzvariablen für die je nach gewünschten Lese- und Schreibzugriff eine eigene Methode existiert. Auf protected und die Feinheiten bei private Elementen wird im Kapitel zum Thema Vererbung genauer eingegangen. Ist ein Klassenelement in der UML Notation unterstrichen, so handelt es sich um ein statisches Element. Ein Beispiel für eine statische Methode ist der Ausführungseinstiegspunkt für die virtuelle Maschine, in Java ist das die public static void main (string args[]) Methode, welche sich also in UML wie folgt darstellen lässt :
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 3
1.2.3 Eigenschaften
Häufig ist es in der Entwurfsphase erforderlich UML Diagramme anzufertigen, und je nach Projektgröße, Qualitäts- und technische Kommunikationsstandards sowie Erweiterbarkeitsbestrebungen zwingend erforderlich. Einige nicht kostenlose UML Tools wie z.B. Sparx Enterprise Systems beinhalten Funktionalitäten wie die programmiersprachenunabhängige Codegerüstgenerierung. Zu fortgeschrittenen Lektionen in der Softwaremodellierung macht es dann auch Sinn solche zu verwenden, wir werden anfangs jedoch uns vorerst beim Erlernen der Programmiersprache und den objektorientierten Paradigmen aufdie manuelle Implementation konzentrieren.
Implementation der Klasse Fahrzeug :
Abbildung in dieser Leseprobe nicht enthalten
Klassen lassen sich im UML Editor Umbrello, nachdem man den Diagrammtyp festgelegt hat, einfach über das Kontextmenü (New->Class) wie folgt erzeugen:
Abbildung in dieser Leseprobe nicht enthalten
4. Abbildung
Ist bereits Code zu einer Klasse vorhanden, wird es oftmals von einigen UML Tools unterstützt, das UML Diagramm auf Basis von importierten Codes zu genieren. Je nach Funktionsumfang des gewählten Tools besteht auch die Möglichkeit Codegerüste aus dem UML Modell zu generieren.
Abbildung in dieser Leseprobe nicht enthalten
5. Abbildung
Ist eine solche Klasse definiert worden, sei es vom Benutzer, also dem Programmierer selber, oder wurde eine solche Klasse aus einer Standardbibliothek oder einer externen Bibliothek importiert, kann diese verwendet werden.
Dazu muss die Klassenquellcodedatei, sofern jene in Java nicht im selben Verzeichnis ist, sondern sich demnach in einem anderen Package befindet, mit dem Schlüsselwort import lokalisiert werden.
Gerade bei kleineren Programmen, ist oftmals die Methode main ebenfalls in der gleichen Klasse definiert. Eine Anforderung seitens dervirtuellen Maschine ist es, dass die Klasse, die ausführbar sein soll, public sein muss. Eine Vorgabe des Compilers ist es wiederum, dass es innerhalb einer Quellcodedatei nur eine public Klasse geben darf. Die Konstellationen können also gerade bei kleineren Testprogrammen sehr individuell sein, wohingegen in größeren Softwareprojekten meistens ein Framework für die Ausführung der Anwendung zur Verfügung steht, welches eine Vielzahl von Initialisierungsvorgängen oder komfortable Funktionalitäten zurVerfügung stellen kann.
Eine mögliche Variante um das Objekt Fahrzeug zu erzeugen, also instantiieren und anschließend zu initialisieren wäre also folgende :
Abbildung in dieser Leseprobe nicht enthalten
Durch die Verwendung des Schlüsselwortes new erhält die virtuelle Maschine zur Laufzeit die Anweisung auf dem Heap (Speicherplatz für Objekte), anstelle des Stacks (Speicherplatz für Variablen), einen bestimmten Bereich des Arbeitsspeichers zu reservieren. Je nach sonstigen Overhead in der Klasse, kann man also davon ausgehen dass durch den Ausdruck new FahrzeugO damit mindestens 32 Bit + 64 Bit + 64 Bit+ 40 Bytes + 40 Bytes = 100 Bytes reserviert werden, dabei wird für ein String mindestens 40 Bytes benötigt. Die praktische Ermittlung der Größe des reservierten Speichers benötigt allerdings einige Workaraounds, da es in Java keinen sizeof Operator gibt.
Da es eine wichtige Anforderung ist das auf die Attribute der Objekte eine Lese- und Schreibzugriffvon außerhalb erfolgen kann, wurden bereits in 1.2.1 Methoden eingeführt.
Methodennamen beginnen in Java i.d.R. mit einem Kleinbuchstaben und zusammengesetzte Wörter werden in Kamelschreibweise formuliert wie z.B. getGewicht (). Eine Variable die zu Beginn, also nach der Definition einer Klasse definiert wurde und nicht static ist, bezeichnet man auch als Instanzvariable, ist diese jedoch static so spricht man von einer Klassenvariable. Gleiches Paradigma gilt auch für Methoden. Verfügt eine private Instanzvariable über mindestens eine get- oder set- Methode, auch „getter“- bzw. „setter“ genannt, so kann auch von einer Property einer Klasse im Sinne des Patterns (Softwaremuster) Bean-Properties gesprochen werden. Die Bezeichnungen Eigenschaft bzw. Attribut bleiben allerdings in der Regel von solchen Implementationsdetails eher unberührt, da jene ihre standardisierte Bedeutung in der Modellierungsphase haben. Handelt es sich bei der Instanzvariable um ein boolean das eingekapselt werden soll, so kann man auch die Abkürzung « is » bzw. « has » voranstellen.
Soll also nun die Instanzvariable preis mit einer Lese und Schreibmethode versehen werden, so sind folgende Codezeilen zu ergänzen :
Abbildung in dieser Leseprobe nicht enthalten
Im UML Diagramm hat das dann folgende Auswirkung :
Methoden können im UML Editor Umbrello durch Selektion der Klasse über das Kontextmenu (Properties) wie folgt definiert werden :
Abbildung in dieser Leseprobe nicht enthalten
7. Abbildung
1.2.4 Konstruktoren
Häufig verfügen Klassen auch über Spezialfunktionalitäten wie zum Beispiel void lichtAnO oder void lichtAn(int intensitaet). Diese Methoden erkennt man dann gleich auf den ersten Blick, da deren Namen nicht mit get/set/is/has anfangen. Eine weitere Spezialmethode ist der Konstruktor. Viele Regeln, die für Methoden gelten, sind auch für Konstruktoren anwendbar, daher kann man in bestimmten Fällen auch von Spezialmethoden sprechen. Wie oben erwähnt, wird jener dann aufgerufen sobald das Schlüsselwort new verwendet wird. Im Konstruktor sollen in der Regel einmalige Initialisierungsaufgaben vorgenommen werden. Prinzipiell ergänzt der Compiler den Klassenquellcode immer um einen Standardkonstruktor, der wie folgt aussieht : [Klassenname] (), also im Fall von Fahrzeug: Fahrzeug () {}. Diese leere Routine die der Compiler eingefügt hat, wird dann bei der Speicherallokation zur Laufzeit von der virtuellen Maschine einfach aufgerufen und abgearbeitet.
Da es in Aufgabe 3 angestrebt wird, die Eigenschaften nach dem Pattern der Bean- Properties einzukapseln, sollten diese per Konvention privat sein. Dadurch wäre es dann nicht mehr möglich auf diese in der main Methode zuzugreifen (f.anzTueren= 4;). Daher kann man zusätzlich zum Standardkonstruktor eine überladene Version explizit einfügen welche die Initialisierung von Variablen vornimmt. Vom Überladen von Methoden oder Konstruktoren spricht man immer dann, wenn es zu einer Methode oder einem Konstruktor unterschiedliche Parameterversionen gibt. Zum Beispiel wäre die Methode lichtAn(int intensitaet) eine überladene Methode von lichtAn(). Genau das gleiche werden wirjetzt für den Standardkonstruktor anfertigen :
Abbildung in dieser Leseprobe nicht enthalten
Dadurch minimiert sich der Codeaufwand in der main Methode wie folgt : public static void main (String args[]) {
Abbildung in dieser Leseprobe nicht enthalten
Zu bemerken ist auch, dass es im Konstruktor sowie bei den Setter-Methoden oftmals zu einer Überschneidung der Gültigkeitsbereiche von Variablen kommt. Dies resultiert auf Grund der gewollten Konvention, dass Variablennamen möglichst eindeutig, leserlich und sinnstiftend über verschiedene Codestellen hinweg verwendet werden sollen. Um nun zwischen einer lokalen Variable, deren Gültigkeit zu Beginn des Methoden- oder Konstruktorcodeblocks beginnt, von einer Instanzvariable zu unterscheiden, wird das Schlüsselwort this der Instanzvariable immer vorangestellt.
1.2.5 Praxisaufgaben
Bitte benutzen Sie zur Lösung der Praxisaufgaben die vereinbarte Entwicklungsumgebung. Legen Sie fürjede Aufgabe ein neues Projekt an.
Aufgabe 3: Vervollständigen Sie die Klasse Fahrzeug Quellcode mit allen geforderten Eigenschaften, definieren Sie diese allerdings als private. Legen Sie zujeder Eigenschaft eine get- und set-Methode an. Überschreiben Sie die toStringO -Methode und geben Sie einen String zum Status des Objekts zurück, der folgendes Ausgabeformat hat : « Herstellername : Anzahl der Türen : Anzahl der Räder : Gewicht : Preis : ». Geben Sie anschließend ihre erzeugten Objekte in der Konsole aus. Wenn die Anwendung fertiggestellt ist, sollten in der Konsole die beiden ersten Zeilen, wie folgt aussehen:
Herstellername:BMWAnzahl der Türen:5 Anzahl der Räder:4 Gewicht:1504.3 Preis:43443.4
Herstellername:Audi Anzahl der Türen:5 Anzahl der Räder:4 Gewicht:1833.2 Preis:55434.23
Aufgabe 4 : Nutzen Sie das Programm UML Umbrello um die Klasse Fahrzeug zu visualisieren. Kopieren Sie das UML Diagramm und die adäquate Quellcodeversion in ein Dokument und drucken Sie dieses aus.
Aufgabe 5 : In einer Webseite für einen Zoo soll aufeiner Übersichtskarte Animationen von attraktiven Tieren per Mouse-Roll-Overeffekt eingespielt werden. Besonders für die Nilpferde, Delphine, Elefanten und Giraffen soll geworben werden. Zu einem Zootier sind die Koordinaten eines Rechtsecks bekannt und ein Verweis auf eine Datei mit den Animationsinstuktionen. Für den Datentyp der zeichenflaeche soll die Klasse Rectangle verwendet werden. Diese ist vor dem Beginn derKlassendefinition mit der Anweisung import java.awt.Rectangle zu importieren. Überschreiben Sie die toString Methode für die Ausgabe einer sinnvollen Tiermeldung. Definieren Sie die Klassen : Nilpferd, Delphin, Elefant und Giraffe in derDatei Zootiere.java. Definieren Sie zum Schluss eine einzige Klasse die public ist und den gleichen Namen wie die Quellcodedatei hat und über eine main-Methode verfügt. Instanziieren Sie im Anschluss einige dieser Tiere.
Aufgabe 6 : Schreiben Sie fürdie Aufgabe 5 eineMethode boolean isMouseOver ( int x, int y) welche überprüft, ob die emulierten Mauskoordinaten innerhalb eines bestimmten Rechtecks liegen. Nutzen Sie wieder die Klasse Rectangle und recherchieren Sie nach einer geeigneten Methode zur Kollisionskennung. Testen Sie anschließend Ihren Code und dokumentieren Sie die Randfälle.
Aufgabe 7 : Für ein Grafikprogramm sollen in der Zeichenpalette die verschiedenen Grundformen Rechteck, Kreis, Dreieck und Stern zur Verfügung stehen. Allen diesen Formen ist es gemeinsam das ihr Startpunkt durch den Klick aufdas linke obere Eck gesetzt wird. Die Größe einer Figur und deren Farbe soll über die Benutzerfläche vorher festgelegt werden. Erstellen Sie daher eine Klasse Figure welche diese Basisinformationen unabhängig von der späteren zeichnerischen Implemenation berücksichtigt. Definieren Sie den Konstruktor Figure (intx, inty, int width, int height, Color c). Die Klasse Color soll vom Packagejava.awt mit der import Anweisung referenziert werden. Kapseln sie die Eigenschaften x, y, width, height und Color mit dem Bean-Property Pattern. Implementieren Sie lediglich eine toString() Methode, welche die jeweiligen Zustände der Objekte aufder « virtuellen Zeichenfläche » als einen String wiedergibt. Zur weiteren Veranschaulichung können Sie die Variable figurename einfügen undjene mit gleicher Lese- und Darstellungsmöglichkeit wie die anderen Variablen ausstatten. Anschließend können Sie die Datei um eine main-Methode erweitern und per Benutzereingaben den Status gezeichneter Objekte testen.
2 Vererbung
2.1 Aufbau einer einfachen Klassenhierarchie
Ähnlich zu den Erkenntnissen der Evolutionsbiologie hinsichtlich der Spezialisierung von Arten, kann man auch im Alltag immer wieder feststellen das eine Gruppe von Objekten Gemeinsamkeiten aufweist. Wobei die Gruppierungskriterien in der Softwareentwicklung wesentlich flexibler sein können. Dennoch macht es immer wieder Sinn sich an der Natur der Dinge und den Naturwissenschaften zu orientieren, sich auf Klassifzierungen auf bestimmte Schemata oder Standards zu beziehen oder falls nicht anders möglich, sich bei proprietären Begrifflichkeiten über ein Pflichtenheft nach Rücksprache mit dem Auftraggeber abzusichern.
2.1.1 Praxisbezug
Ziel im Kapitel 4 soll es sein ein kleines Grafikprogramm zu entwickeln in welchem die einfachen geometrische Objekte : Kreis, Rechteck und Dreieck dargestellt werden können. Jedes dieser Objekte verfügt über eine bestimmten Start- und Endpunkt. Zwischen diesen beiden Punkten wird dann die jeweilige Figur in einer bestimmten zuvor festgelegten Farbe gezeichnet. Tatsächlich, wie wir allerdings später feststellen werden, werden die Objekte in einer dynamischen Datenstruktur abgelegt welche in einer Methode zum Zeichnen vom GUI-Thread dann durchlaufen wird. Jedes zu zeichnende Objekt muss dann zu diesem Zeitpunkt genug Statusinformationen zur Verfügung haben um die Zeichenfläche befüllen zu können, wie nachfolgender Abbildung zu entnehmen ist :
Abbildung in dieser Leseprobe nicht enthalten
Abbildung 8
Immer dann wenn eine Vielzahl von Gemeinsamkeiten zwischen verschiedenen Objekten vorhanden ist, bietet es sich an, eine Basisklasse zu konzipieren. Durch die Bildung von Basisklassen ergeben sich folgende Vorteile : zum einen entsteht eine logische hierarchische Struktur im Klassendiagramm, zum anderen wird versucht Codestellen die die gleiche Funktion haben zu zentralisieren (Reduzierung der Fehleranfälligkeit, Verbesserung der Effizienz und ggf. der Performanz) und in der Regel wird die Organisation der Arbeitsteilung bei der Softwarentwicklung erleichtert. Da ein Konstruktor nichts weiter als eine spezielle Methode ist, bietet es sich natürlich auch bereits in der Basisklasse an, immer wieder auftretende Eigenschaften frühzeitig zu initialisieren. Wir entschließen uns daher für die Realisierung folgender Basisklasse, die alle bekannten Gemeinsamkeiten vereint :
Abbildung in dieser Leseprobe nicht enthalten
Zu bemerken ist am oberen Codebeispiel das die Anweisung import verwendet wurde. Dies ist immer dann notwendig, wenn sich eine Klasse nicht im standardmäßig importierten Package java.lang.* befindet oder auf ein andere Klasse im API zugegriffen werden soll. Strenggenommen handelt es sich im objektorientierten Sinne dann um einen Aggregation (has a, - Beziehung). Dieser Beziehungstyp darf nicht mit einer generischen Beziehung, nämlich der Vererbung (is a - Beziehung) verwechselt werden. Auch hier bietet es sich immer wieder an, sich an der Natur der Dinge, manchmal auch vom Menschen geschaffen zu orientieren. Zum Beispiel ist ein Auto ein Fahrzeug und hat Räder und es hat Türen. Die Vererbungsbeziehung ist daher zwischen Fahrzeug und Auto, Fahrzeug ist die Basisklasse und Auto die Subklasse. Die Aggregationsbeziehung besteht zwischen Auto, Reifen und Türen. Wie oben erwähnt liegt der unmittelbare Vorteil in der Wiederverwendung von Eigenschaften und Methoden die von der Basisklasse vererbt werden. Jene müssen also nicht in Subklassen erneut definiert werden, es sei denn sie sollen überschrieben werden, was wiederum auch durch den Zugriffmodifikator private sogar verhindert werden kann. Ausnahmen zu dieser Regelung bilden Konstruktoren in Java, da diese zwar der Subklasse zur Verfügung stehen, allerdings müssen jene Konstruktoren die wiederum außerhalb der Klasse nutzbar sein sollen überschrieben werden. Dadurch wird sichergestellt das die Verantwortung bezüglich der Initialisierung der Klasse beim jeweiligen Autor bleibt.
Mit dem Schlüsselwort extends wird eine Vererbungsbeziehung zum Ausdruck gebracht. Daher ergeben sich nun für die Subklassen folgende Beispielcodes die idealerweise in eigenen Dateien abgespeichertwerden: public class Rectange extends Figure {
Abbildung in dieser Leseprobe nicht enthalten
Wie bereits erwähnt, sind Konstruktoren in vielerlei Hinsicht mit Methoden vergleichbar, allerdings gilt insbesondere in Java zu beachten, das diese Elemente nicht explizit vererbt werden. Daher ist es erforderlich für verschiedene Subklassen Konstruktoren die vom Standardkonstruktor abweichen, individuell zu definieren. Dennoch sollte auch hier wieder
wie beim Überschreiben von Methoden auf eine Codezentralität geachtet werden. Das heißt in beiden Fällen sollten Aktivitäten die bereits in der Basisklasse innerhalb einer Methode oder innerhalb eines Konstruktors durchgeführt wurden, wieder aufgerufen und verwendet werden. Für diese Delegation gibt es das Schlüsselwort supero dem dann die entsprechenden Parameter für die gewünschte Verkettung zur Basismethode oder Basiskonstruktor übergeben wird. Um bspw. den Rückgabewert der toString() Methode der Basisklasse in einen Rückgabe-String zu verarbeiten ist es auch möglich das Schlüsselwort super wie folgt zu kombineren:
Abbildung in dieser Leseprobe nicht enthalten
Innerhalb einer Klasse kann ähnliches mit this() erreicht werden um z.B. verschiedene Konstruktorversionen miteinander in Beziehung zu setzen. Um nun bspw. die Klasse mit der notwendigen Konstruktor auszustatten ist es erforderlich diesen zu implementieren :
Abbildung in dieser Leseprobe nicht enthalten
Im UML Diagramm haben Vererbungsbeziehungen wiederum folgendeAuswirkungen:
Abbildung in dieser Leseprobe nicht enthalten
9. Abbildung
Wobei zur Abb. 6 anzumerken ist, dass in diesem UML Diagramm bereits die komplette Zielstellung von Aufgabe 10 dargestellt ist und das sich die Klassen im Package model befinden. Ferner kann man auch sehen, dass die Methode paintMe der Basisklasse kursiv dargestellt ist, d.h. diese Methode ist abstrakt.
Ein Pfeil der eine äußere Umrandung in Form eines Dreiecks hat, symbolisiert dabei eine Vererbung und einer der nur durch zwei Striche angedeutet ist, stellt dabei eine Aggregation dar. Vererbte Eigenschaften und Methoden können dann genauso genutzt werden, wie wenn das Element in der Subklasse definiert wurde, außer es wurde in der Basisklasse derZugriffsmodifikator private verwendet.
Abbildung in dieser Leseprobe nicht enthalten
Die Schreibweise Color.green ist nichts weiter als eine Abkürzung für new Color (0,255,0). Wobei im zweiten Fall die RGB Werte bekannt sein müssen die bei Mischfarben oftmals erst über eine Farbpalette ermittelt werden müssen. In der Klasse Color sind daher diverse Standardfarben als öffentliche konstante Klassenvariablen realisiert (final static). Dadurch ist es nicht notwendig explizit eine Instanz anzulegen, da einfach aufdie bereits initialisierte Konstante verwiesen werden kann.
2.1.2 Praxisaufgaben
Aufgabe 9 : Erweitern Sie die Aufgabe 5 mit einerBasisklasse Tier. Diese Basisklasse verfügt per Aggregation überein Rectangle zeichenflaeche undeinenString dateiverweis. Leiten Sie von derKlasse Tier nun die Klasse Nilpferd, Delphin, Elefant und Giraffe ab. Definieren Siejeweils eine spezifische toStringO Methode welche eine Ausgabe zum jeweiligen Tiertyp macht. Verlagern Sie nun die vier boolean isMouseOver ( int x, int y) MethodenausAufgabe6indieKlasse Tier.Diese Methode soll für alle Subklassen gültig sein und dort nicht mehr überschrieben werden. Auch sollten Instanzvariablen nicht mehr redefiniert werden. Instanziieren Sie anschließend die verschiedenen Subklassen in einer main Methode und geben Sie denjeweilige Tierbeschreibung in der Konsole aus. Markieren Sie die Klasse Tier im Anschluss als abstrakt, bringen Sie damit zum Ausdruck das es nicht gewünscht ist eine Instanz von Tier zu bilden.
Aufgabe 10 : Die Klasse Figure aus Aufgabe 7 soll nun eine abstrakte Basisklasse werden. Fürden FalldasspätereSubklassendieBean-Properties x, y, width, height, color initialisieren müssen, wird ein Konstruktorzur Verfügung gestellt aufdie sich dann die Subklassen mit super beziehen können. Da es zum jetzigen Projektzeitpunkt noch nicht feststeht wie ein Grafikobjekt im späteren Zeichenprogramm instantiiert werden soll, muss auch davon ausgegangen werden, dass die Standardkonstruktoren genutzt werden. Erstellen Sie anschließend die Subklassen Circle, Triangle, und Rectangle. Definieren Sie die Methode void paintMe (java.awt.Graphics g) in derBasisklasse Figure alsabstraktundschreiben Sie für die Subklassen Dummy-Implementationen. Überschreiben Sie die toString() Methode in den Subklassen. Die Subklassen sollen dabei nur noch die Typinformation hinzufügen.
Aufgabe 11 : Führen Sie die Klasse Stern mit sechs Spitzen ein. Erweitern Sie das obige UML Digramm zeichnerisch.
[...]
-
-
-
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X. -
-
Téléchargez vos propres textes! Gagnez de l'argent et un iPhone X.