Vollständiges OOP-Beispiel

Socken

Die Sockenklasse

Implementiere eine Klasse Socke mit den sich aus dem UML-Diagramm ergebenden Eigenschaften:

UML-Diagramm einer Socke

Implementiere trockne() und wasche() so, dass der interne Zustand istTrocken geändert wird. Das heißt, eine trockene Socke setzt den Zustand von istTrocken auf true. Die Methode istTrocken() ist eine Zugriffsmethode und gibt den internen Zustand des Attributes istTrocken nach außen.

Schreibe in einer anderen Klasse einen Funktionstest in die main(...)-Methode, etwa so:

Socke omisSocke = new Socke();
omisSocke.wasche();
System.out.println( omisSocke.istTrocken() );

Lösung

Zugriffsrechte

Was bedeuten die Zugriffsrechte öffentlich (public), protected, paketsichtbar (kein Modifizierer) und privat (private). Überlege, welche Attribute privat und welche öffentlich sein sollten.

Lösung

Die java.lang.Object Methoden

Die Oberklasse java.lang.Object gibt allen Objekten die Methode toString() weiter. Implementiere toString() in der Klasse Socke. Welche Signatur muss die Methode haben?

Lösung

Konstruktoren

Implementiere einen Konstruktor, der farbige Socken initialisiert. Schreibe zusätzlich einen Standard-Konstruktor, der den Socken die Farbe Schwarz gibt.

UML-Diagramm eines Konstruktors

Erweitere das Programm, sodass der Standard-Konstruktor den parametrisierten Konstruktor nutzt. (Das war die Sache mit dem this(...)).

Lösung

Statische Methoden

Implementiere eine Umwandlung von Farbnamen in Color-Objekte durch eine statische Methode. Betrachte die Klasse java.awt.Color. Fülle folgende Signatur

public static Color stringToColor( String s ) {
}

Liefere die Farbe Color.BLACK, falls ein Farbwert unbekannt ist.

Lösung mit if-else
Lösung mit einem Array

Objektverweise

Farben müssen nicht zwingend durch Namen (Strings) angegeben werden. Es gibt auch die Möglichkeit, spezielle Farb-Objekte zu erzeugen. Ersetze

String farbe;

durch

Color farbe;

Implementiere einen Konstruktor so, dass er Color-Objekte annimmt und speichert. Rufe den Konstruktor mit dem Parameter Color.BLUE auf.

Den alten Konstruktor soll man noch verwenden können. Nutze dazu die statische Methode stringToColor(...).

Wird die Socke gewaschen, so soll die Farbe ausgewaschen werden. Suche in der API-Dokumentation nach einer Methode, die Farbwerte aufhellt.

Vererbung

Leite die Klasse Socke von der Oberklasse Kleidung ab.

UML-Diagramm einer Vererbungsbeziehung

Nehme zusätzlich eine Klasse Hose hinzu, die ebenfalls von Kleidung ableitet. Überlege, welche Eigenschaften in die Oberklasse bewegt werden sollen. Belasse toString() in der Unterklasse.

Lösung für Kleidung
Lösung für Hose
Lösung für Socke

Das ist super

Implementiere trockne() in den Unterklassen so, dass eine kurze Meldung auf dem Bildschirm erscheint. Die alte Implementierung aus der Oberklasse soll dennoch aufgerufen werden.

Abstrakte Klassen

Kann es das Kleidungsstück geben? Nein! Daher sollten wir Kleidung abstract deklarieren. Die konkreten Objekte sind aber vom Typ Kleidung. Daher lässt sich schreiben:

Kleidung cord = new Hose( "Blau" );

Wir wollen nun die Methoden setzeWaschZeit(int) als abstrakte Methoden in Kleidung angeben. Dann müssen die Unterklassen diese Methoden überschreiben. (Andernfalls könnte man ja kein Hose/Socke-Exemplar erzeugen.) Abstrakte Methoden haben keine Implementierung, sodass wir in Kleidung etwa schreiben:

abstract void setzeWaschZeit();      

Schnittstellen/Interfaces

Implementiere die Schnittstelle Waschbar für Kleidung. Überlege, wo die Methoden zu implementieren sind. Lasse dann Kleidung die Schnittstelle Waschbar implementieren.

Da nun jedes konkrete Kleidungsstück waschbar ist, lässt sich schreiben:

Waschbar jeans = new Hose( "Blau" );

Jetzt kann man auf der jeans nur noch die Methoden der Schnittstelle verwenden. Wäre es günstig gewesen, Hose und Socke die Schnittstelle Waschbar implementieren zu lassen?

Container durch Arrays

Implementiere eine Klasse Waescheleine, die maximal 10 Kleidungsstücke aufnehmen kann.

UML-Diagramm einer Wäscheleine

Lege die 10 als Konstante an. Füge eine Methode add(Kleidung) ein. Die Kleidungsstücke sollen in einem privaten Array aufgenommen werden, das Objekte vom Typ Kleidung aufnimmt. Mit get(index) soll der Zugriff auf die Elemente erlaubt werden. Die Anzahl der Elemente soll man mit length() erfahren können.

Lösung

Exception-Handling

Werden mehr als 10 Elemente eingefügt, so könnte zum Beispiel die Wäscheleine andere Elemente entfernen. Der Versuch, ein elftes Element hinzuzufügen, soll mit einer java.lang.IndexOutOfBoundsException bestraft werden. Da dies eine Unterklasse von java.lang.RuntimeException ist, muss sie nicht gesondert aufgefangen werden.

Löse bewusst diesen Fehler auf, in dem ein 11. Element eingefügt wird. Fange den Fehler mit einer try-catch-Anweisung auf.

Implementiere eine eigene Fehlerklasse ZuVielAufgehangenException. Leite sie von java.lang.RuntimeException ab.

Polymorphie

Die Klasse Waescheleine soll nun ebenfalls eine Methode trockne() bekommen. Sie ruft aber trockne() auf allen Kindern auf. Implementiere dann trockne() auf den Kindern so, dass eine kurze Meldung erscheint.