Objektorientierte Programmiertechniken
LVA 185.A01, VU, 3 ECTS, 2015/2016 W
| Ausgabe: | 11.11.2015 |
| Abgabe: | 18.11.2015, 12:00 Uhr |
BasicSet stellt eine Menge dar, deren Elementtypen durch
einen Typparameter bestimmt werden.
BasicSet implementiert das Interface java.lang.Iterable sowie folgende Methoden:
add nimmt als Argument ein Element, das in die Menge eingefügt wird,
wenn nicht bereits das identische Element vorhanden war.
Mehrere gleiche Elemente dürfen in der Menge sein (aber nicht mehrere identische).
iterator liefert als Ergebnis einen Iterator, über
den nacheinander auf alle Elemente der Menge in einer nicht weiter
bestimmten Reihenfolge zugegriffen werden kann.
Der Iterator muss auch remove implementieren und darf keine
UnsupportedOperationException werfen (siehe java.lang.Iterator).
SortedSet stellt eine Menge dar,
die wie BasicSet das Interface java.lang.Iterable implementiert.
Ein Typparameter bestimmt den Typ der Elemente.
Die Elemente müssen das Interface Smaller mit der Methode
smaller mit einem Parameter unterstützen, die genau dann
true zurückgibt, wenn this (auf nicht näher
bestimmte Weise) kleiner als das übergebene Argument ist.
SortedSet implementiert folgende Methoden:
add entspricht der gleichnamigen Methode in BasicSet.
iterator liefert als Ergebnis einen Iterator, über den
nacheinander auf alle Elemente der Menge zugegriffen werden kann,
wobei nachfolgende Elemente entsprechend smaller niemals
kleiner sein dürfen als vorangegangene.
Der Iterator muss remove implementieren und darf keine
UnsupportedOperationException werfen.
SortedSet soll ein Untertyp von BasicSet sein.
Smaller beschreibt nur die boolesche
Methode smaller, die zwei Objekte zusammenpassender Typen miteinander vergleicht.
MyInteger, die das Interface
Smaller<...> implementiert, enthält als Wert eine ganze Zahl,
die über den Konstruktor gesetzt wird. Die Methode smaller(x)
entspricht dabei dem kleiner-Vergleich auf ganzen Zahlen. MyInteger hat KEINE
Untertypbeziehung zur folgenden Klasse Bauholz.
Bauholz enthält
die Länge eines Bauholzes in cm als ganze Zahl, die über den Konstruktor gesetzt wird.
Weiters enthällt Bauholz die abstrakte Methode festmeter,
die das Volumen (in Festmeter) des Bauholzes als Gleitkommazahl zurückliefert.
Die abstrakte Klasse soll Smaller<...> implementieren,
wobei x.smaller(y) genau dann gelten soll, wenn x.festmeter() kleiner
y.festmeter() ist.
Baurundholz erweitert Bauholz um die Angabe des
Durchmessers in cm (ganze Zahl), der im Konstruktor gesetzt wird.
Baukantholz erweitert Bauholz um die Angabe der
Breite und Höhe in cm (ganze Zahl), die im Konstruktor gesetzt werden.
Ein Aufruf von java Test soll wie gewohnt Testfälle ausführen
und die Ergebnisse in allgemein verständlicher Form darstellen.
Anders als in bisherigen Aufgaben sind die Überprüfungen jedoch
vorgegeben und in dieser Reihenfolge auszuführen:
BasicSet<Integer>,
SortedSet<MyInteger>,
SortedSet<Baurundholz> und SortedSet<Baukantholz>,
fügen Sie jeweils einige Elemente ein, und geben Sie alle Elemente
(bei Bauholz inklusive Durchmesser bzw. Breite und Höhe) so aus,
dass die Struktur sichtbar wird.
Geben Sie die Elemente von SortedSet<Baurundholz> und
SortedSet<Baukantholz> in entsprechend smaller
sortierter Reihenfolge aus.
Entfernen Sie Elemente, fügen Sie Elemente ein und
geben Sie die Inhalte der Datenstrukturen erneut aus.
SortedSet<Bauholz>.
Lesen Sie über Iteratoren alle Elemente aus den in Punkt 1
erzeugten Datenstrukturen der Typen SortedSet<Baurundholz>
und SortedSet<Baukantholz> aus und fügen Sie
diese in die neue Datenstruktur ein.
Überprüfen Sie die Funktionalität der Datenstruktur
wie in Punkt 1, allerdings ohne Durchmesser bzw. Breiten und
Höhen auszugeben.
BasicSet<Bauholz> wäre (z.B.,
indem Sie die Datenstruktur an eine Variable vom deklarierten Typ
BasicSet<Bauholz> zuweisen und die folgenden Tests
auf dieser Variablen ausführen).
Testen Sie die Funktionalität wie in Punkt 1, allerdings
ohne Durchmesser bzw. Breiten und Höhen auszugeben und die
zusätzliche Funktionalität von SortedSet zu verwenden.
Daneben soll die Klasse Test.java als Kommentar eine kurze, aber verständliche Beschreibung der Aufteilung der Arbeiten auf die einzelnen Gruppenmitglieder enthalten – wer hat was gemacht.
Alle Teile dieser Aufgabe sind ohne Verwendung von Arrays, ohne vorgefertigte Container-Klassen (wie LinkedList, HashSet, etc.) und ohne vorgefertigte Iterator-Implementierungen zu lösen. Benötigte Container und Iteratoren sind selbst zu schreiben.
Typsicherheit soll so weit wie möglich vom Compiler garantiert werden.
Auf die Verwendung von Typumwandlungen (Casts) und ähnliche Techniken
ist zu verzichten, und der Compiler darf keine Hinweise auf mögliche
Probleme im Zusammenhang mit Generizität geben.
Achtung: Übersetzen Sie die Klassen mittels
javac -Xlint:unchecked *.java; dieses Compiler-Flag schaltet
genaue Compiler-Meldungen im Zusammenhang mit Generizität ein.
Andernfalls bekommen Sie auch bei schweren Fehlern vom Compiler nur
eine harmlos aussehende Meldung (Note: ...
).
Überprüfungen durch den Compiler dürfen nicht ausgeschaltet
werden, auch nicht für Warnungen.
Durch die Typhierarchie auf Bauholz, Baurundholz
und Baukantholz muss Generizität über mehrere Ebenen
hinweg betrachtet werden, da vereinfachende Sichtweisen durch die von
dieser Hierarchie unabhängigen Typen SortedSet<Bauholz>,
SortedSet<MyInteger> und BasicSet<Integer>
ausgeschlossen sind.
Vorgegebene Testfälle stellen sicher, dass die Schwierigkeiten erkannt werden. Um Umgehungen zu vermeiden sind Typumwandlungen ebenso verboten wie das Ausschalten von Compilerhinweisen auf unsichere Verwendungen von Generizität. Neben Techniken zur Lösung der speziellen Schwierigkeiten wird in dieser Aufgabe auch der Umgang mit Sichtbarkeit und Untertypbeziehungen auf generischen Typen geübt. Am Beispiel von Iteratoren soll intuitiv klar werden, welchen Einfluss die Verwendung innerer Klassen auf die Sichtbarkeit von Implementierungsdetails nach außen hat.
| Generizität zusammen mit geforderten Untertypbeziehungen richtig verwendet, sodass die Tests (ohne Tricks beim Testen) durchführbar sind | 35 Punkte |
| Zusicherungen richtig und sinnvoll eingesetzt | 15 Punkte |
| Sichtbarkeit auf so kleine Bereiche wie möglich beschränkt | 15 Punkte |
| Lösung wie vorgeschrieben und sinnvoll getestet | 20 Punkte |
| Geforderte Funktionalität vorhanden (so wie in Aufgabenstellung beschrieben) | 15 Punkte |
Am wichtigsten ist die sinnvolle und korrekte Verwendung von Generizität. Es gibt bedeutende Punkteabzüge, wenn der Compiler mögliche Probleme im Zusammenhang mit Generizität meldet oder wichtige Teilaufgaben nicht gelöst oder umgangen werden.
Ein zusätzlicher Schwerpunkt liegt auf dem gezielten Einsatz von Sichtbarkeit.
Es gibt Punkteabzüge, wenn Programmteile, die überall sichtbar sein sollen, nicht public sind, oder Teile, die nicht für die allgemeine Verwendung bestimmt sind, unnötig weit sichtbar sind.
Durch die Verwendung innerer Klassen kann das Sichtbarmachen mancher Programmteile nach außen verhindert werden.
Nach wie vor spielen auch Untertypbeziehungen und Zusicherungen eine große Rolle bei der Beurteilung.
Generell führen Abänderungen der Aufgabenstellung – beispielsweise die Verwendung von Typumwandlungen, Arrays oder vorgefertigten Containern und Iteratoren oder das Ausschalten von Überprüfungen durch @SuppressWarning – zu bedeutenden Punkteabzügen.