Objektorientierte Programmiertechniken
LVA 185.A01, VU, 3 ECTS, 2016/2017 W
6. Übungsaufgabe
Themen:
dynamische Typinformation, homogene Übersetzung von Generizität
Termine:
| Ausgabe: |
30.11.2016 |
| Abgabe: |
07.12.2016, 12:00 Uhr |
Abgabeverzeichnis:
Aufgabe6
Programmaufruf:
java Test
Grundlage:
Skriptum, Schwerpunkt auf den Abschnitten 3.3.1 und 3.3.2
Aufgabe
Welche Aufgabe zu lösen ist:
Die Eichhörnchen haben schon viele Vorräte gesammelt, sie verlieren allerdings schon den Überblick über ihre Verstecke.
Sie benötigen ein Programm zur Verwaltung ihre Verstecke und Vorräte.
Jedes Versteck hat eine eindeutige, unveränderliche Nummer (ganze Zahl) und ein Volumen (Gleitkommazahl).
Es gibt zwei Arten von Verstecken, Baumverstecke und Erdverstecke.
Bei einem Baumversteck wird der Name der Baumart (Zeichenkette) und die Höhe (ganze Zahl), in der sich das Versteck befindet, gespeichert.
Bei einem Erdversteck werden die X- und Y-Koordinaten (Gleitkommazahlen) des Verstecks relativ zum Nest (Koordinaten 0,0) des Eichhörnchen gespeichert.
Ein Versteck kann entweder für Nüsse oder für Samen genützt werden (aber nicht beides gleichzeitig).
Das selbe Versteck kann aber abwechselnd hintereinander für Nüsse oder Samen genützt werden.
Wird ein Versteck für Nüsse genützt, wird die Anzahl der Nüsse gespeichert (ganze Zahl).
Wird ein Versteck für Samen genützt, wird das Gewicht der Samen gespeichert (Gleitkommazahl).
Entwickeln Sie Java-Klassen bzw. Interfaces zur Darstellung von Verstecken auch für unterschiedliche Nahrungsmittelarten.
Folgende Funktionalität soll unterstützt werden:
- Erzeugen eines Verstecks.
- Auslesen des Volumens eines Verstecks.
- Auslesen des Namens der Baumart und der Höhe eines Baumverstecks.
- Auslesen der Entfernung zum Nest eines Erdverstecks (Wurzel aus der Summe der Quadrate der X- und Y-Koordinate).
- Ändern der Nahrungsmittelart eines Verstecks, wobei Informationen über frühere Nahrungsmittelarten dieses Verstecks verloren gehen.
- Ändern der Anzahl der Nüsse oder des Gewichts der Samen.
- Auslesen der Anzahl der Nüsse oder des Gewichts der Samen.
Schreiben Sie eine Klasse Eichhoernchen, die Informationen über ein Eichhörnchen verwaltet und statistische Auswertungen über dieses Eichhörnchen ermöglicht.
Jedes Eichhörnchen hat einen unveränderlichen Namen (Zeichenkette).
Folgende Methoden sollen unterstützt werden:
- Erzeugen eines Eichhörnchens.
- Hinzufügen von Verstecken zu einem Eichhörnchen.
- Entfernen von Verstecken von einem Eichhörnchen.
- Ändern der Informationen von Verstecken wie oben beschrieben.
- Methoden zum Berechnen folgender statistischer Werte:
- Das durchschnittliche Volumen aller Verstecke eines Eichhörnchens – alle Verstecke zusammen und zusätzlich aufgeschlüsselt nach den Nahrungsmittelarten (Nüsse oder Samen).
- Das durchschnittliche Volumen aller Verstecke eines Eichhörnchens aufgeschlüsselt nach den Verstecksarten (Baum oder Erd).
- Die durchschnittliche Höhe aller Baumverstecke eines Eichhörnchens – alle zusammen und zusätzlich aufgeschlüsselt nach den Nahrungsmittelarten (Nüsse oder Samen).
- Die durchschnittliche Entfernung zum Nest aller Erdverstecke eines Eichhörnchens – alle zusammen und zusätzlich aufgeschlüsselt nach den Nahrungsmittelarten (Nüsse oder Samen).
- Die durchschnittliche und maximale Anzahl der Nüsse aller Verstecke mit Nüssen eines Eichhörnchens insgesamt und aufgeschlüsselt nach Art des Verstecks (Baum oder Erd).
- Das durchschnittliche und maximale Gewicht der Samen aller Verstecke mit Samen eines Eichhörnchens insgesamt und aufgeschlüsselt nach Art des Verstecks (Baum oder Erd).
Schreiben Sie eine Klasse Kolonie, die Informationen über alle Eichhörnchen einer Kolonie verwaltet.
Jede Kolonie hat einen unveränderlichen Namen.
Folgende Methoden sollen unterstützt werden:
- Erzeugen einer Kolonie.
- Hinzufügen von Eichhörnchen zu einer Kolonie.
- Entfernen von Eichhörnchen aus einer Kolonie.
- Anzeigen aller Eichhörnchen einer Kolonie mit allen Informationen (inklusive Verstecken) auf dem Bildschirm.
Die Klasse Test soll die wichtigsten Normal- und Grenzfälle (nicht interaktiv) überprüfen und die Ergebnisse in allgemein verständlicher Form in der Standardausgabe darstellen.
Machen Sie unter anderem Folgendes:
- Erstellen und ändern Sie mehrere Kolonien mit mehreren Eichhörnchen mit jeweils einigen Verstecken.
Jedes Eichhörnchen einer Kolonie soll über seinen eindeutigen Namen angesprochen werden, und jedes Versteck eines Eichhörnchens über seine eindeutige Nummer.
- Fügen Sie zu Kolonien einzelne Eichhörnchen hinzu, entfernen Sie einzelne Eichhörnchen, wobei Sie Eichhörnchen nur über deren Namen ansprechen.
- Fügen Sie zu einigen Eichhörnchen einzelne Verstecke hinzu, entfernen Sie einzelne Verstecke, und ändern Sie die Informationen zu einzelnen Verstecken, wobei Sie Verstecke und Eichhörnchen nur über deren Nummern und Namen ansprechen.
- Berechnen Sie die statistischen Werte aller Eichhörnchen (wie oben beschrieben).
Generizität, Arrays und vorgefertigte Container-Klassen dürfen zur Lösung dieser Aufgabe nicht verwendet werden.
Vermeiden Sie mehrfach vorkommenden Code für gleiche oder ähnliche Programmteile.
Warum die Aufgabe diese Form hat:
Die gleichzeitige Unterscheidung von unterschiedlichen Verstecken sowie zwischen unterschiedlichen Nahrungsmitteln stellt eine Schwierigkeit dar, für die es mehrere sinnvolle Lösungsansätze gibt.
Sie werden irgendeine Form von Container selbst erstellen müssen, wobei die genaue Form und Funktionalität nicht vorgegeben ist.
Da Container an mehreren Stellen benötigt werden, wäre die Verwendung von Generizität sinnvoll.
Dadurch, dass Sie Generizität nicht verwenden dürfen und trotzdem mehrfache Vorkommen ähnlichen Codes vermeiden sollen, werden Sie gezwungen, Techniken ähnlich denen einzusetzen, die der Compiler zur homogenen Übersetzung von Generizität verwendet.
Vermutlich sind Typumwandlungen kaum vermeidbar.
Sie sollen dadurch ein tieferes Verständnis des Zusammenhangs zwischen Generizität und Typumwandlungen bekommen.
Was im Hinblick auf die Beurteilung zu beachten ist:
Die insgesamt 100 für diese Aufgabe erreichbaren Punkte sind folgendermaßen auf die zu erreichenden Ziele aufgeteilt:
| Container richtig und wiederverwendbar implementiert, Typumwandlungen korrekt |
35 Punkte |
| Geforderte Funktionalität vorhanden (so wie in Aufgabenstellung beschrieben) |
20 Punkte |
| Lösung wie vorgeschrieben und sinnvoll getestet |
20 Punkte |
| Zusicherungen richtig und sinnvoll eingesetzt |
15 Punkte |
| Sichtbarkeit auf so kleine Bereiche wie möglich beschränkt |
10 Punkte |
Der Schwerpunkt bei der Beurteilung liegt auf der vernünftigen Verwendung von dynamischer und statischer Typinformation.
Kräftige Punkteabzüge gibt es für
- die Verwendung von Generizität bzw. von Arrays oder vorgefertigten Container-Klassen
- mehrfach vorkommende gleiche oder ähnliche Programmteile (wenn vermeidbar)
- den unnötigen Verlust an statischer Typsicherheit
- Verletzungen des Ersetzbarkeitsprinzips bei Verwendung von Vererbungsbeziehungen (also Vererbungsbeziehungen, die keine Untertypbeziehungen sind)
- und mangelhafte Funktionalität des Programms.
Punkteabzüge gibt es unter anderem auch für mangelhafte Zusicherungen und falsche Sichtbarkeit.
Wie die Aufgabe zu lösen ist:
Es wird empfohlen, die Aufgabe zuerst mit Hilfe von Generizität zu lösen und in einem weiteren Schritt eine homogene Übersetzung der Generizität (wie im Skriptum beschrieben) händisch durchzuführen.
Durch diese Vorgehensweise erreichen Sie eine statische Überprüfung der Korrektheit vieler Typumwandlungen und vermeiden den unnötigen Verlust an statischer Typsicherheit.
Zur Lösung dieser Aufgabe ist die Verwendung von Typumwandlungen ausdrücklich erlaubt.
Versuchen Sie trotzdem, die Anzahl der Typumwandlungen klein zu halten und so viel Typinformation wie möglich statisch vorzugeben.
Das hilft Ihnen dabei, die Lösung überschaubar zu halten und einen unnötigen Verlust an statischer Typsicherheit zu vermeiden.
Gehen Sie auch möglichst sparsam mit dynamischen Typabfragen und Ausnahmebehandlungen um.
Achten Sie darauf, dass Sie Divisionen durch 0 vermeiden.
Führen Sie zumindest einen Testfall ein, bei dem eine statistische Auswertung ohne entsprechende Vorkehrungen eine Exception aufgrund einer Division durch 0 auslösen würde.
Bedenken Sie, dass es mehrere sinnvolle Lösungsansätze für diese Aufgabe gibt.
Wenn Sie einmal einen gangbaren Weg gefunden haben, bleiben Sie dabei, und vermeiden Sie es, zu viele Möglichkeiten auszuprobieren.
Das könnte Ihnen viel Zeit kosten, ohne die Lösung zu verbessern.
Die Art der Verwendung eines Verstecks für unterschiedliche Nahrungsmittel kann sich im Laufe der Zeit ändern.
Am besten stellt man solche Beziehungen über Rollen dar:
Für jede Art von Versteck gibt es eine eigene Klasse mit den für die jeweilige Art typischen Daten, und ein gemeinsamer Obertyp ermöglicht den Zugriff auf diese Daten auf einheitliche Weise.
In jedem Versteck gibt es einen Referenz auf die aktuelle Nahrungsmittelart (= die Rolle, die das Versteck gerade spielt).
Wenn sich die Art ändert, braucht nur diese Referenz neu gesetzt zu werden.
Durch geschickte Auswahl der Methoden einer Rolle sind die meisten Fallunterscheidungen vermeidbar, das heißt, Fallunterscheidungen werden durch dynamisches Binden ersetzt.
Was im Hinblick auf die Abgabe zu beachten ist:
Schreiben Sie (abgesehen von geschachtelten Klassen) nicht mehr als eine Klasse in jede Datei.
Verwenden Sie keine Umlaute in Dateinamen.
Achten Sie darauf, dass Sie keine Java-Dateien abgeben, die nicht zu Ihrer Lösung gehören (alte Versionen, Reste aus früheren Versuchen, etc.).