Blatt 02: Zoo (Generics, Collections, Gradle)

(1 Punkt)

Dieses Blatt ist bewusst einfach gestaltet und dient zum Teil der Wiederholung Ihrer Kenntnisse aus der LV "Programmieren 1".

A02.1: Gradle (15%)

Folgen Sie der Anleitung auf gradle.org und installieren Sie Gradle auf Ihrem Rechner. Legen Sie in der Konsole ein neues Gradle-Projekt für eine Java-Applikation an (ohne IDE!). Das Build-Script soll in Groovy erzeugt und als Test-API soll JUnit4 verwendet werden.

Wie finden Sie auf der Konsole heraus, welche Tasks es gibt? Erklären Sie das Projektlayout, d.h. wo kommen beispielsweise die Java-Dateien hin?

Erklären Sie, in welche Abschnitte das generierte Buildskript unterteilt ist und welche Aufgaben diese Abschnitte jeweils erfüllen. Gehen Sie dabei im Detail auf das Plugin application und die dort bereitgestellten Tasks und deren Abhängigkeiten untereinander ein.

Öffnen Sie das Projekt in Ihrer IDE. Wie können Sie hier die verschiedenen Tasks ansteuern?

Machen Sie sich Notizen, welche Sie im Praktikum nutzen dürfen, um dort das Buildskript zu erklären.

Zoo

Sie finden in den Vorgaben im Package zoo einige Interfaces und Klassen, mit denen man einen Zoo modellieren kann.

Laden Sie sich die Vorgaben im Browser von GitHub herunter1, entpacken Sie das Zip-File und laden Sie den Ordner als Gradle-Projekt in Ihre IDE.

A02.2: Nicht-generische Klassen (10%)

Sie finden einige Interfaces, die das Interface Animal erweitern, beispielsweise Fish, Reptile, Cat, ...

Erstellen Sie für jedes dieser Interfaces jeweils zwei Java-Klassen, die konkrete Mitglieder der jeweiligen Tier-Klasse bzw. -Familie2 repräsentieren und die jeweils das Interface implementieren. Beispielsweise könnte eine Forelle eine Art in der Klasse der Fische sein, d.h. die Java-Klasse Trout könnte das Interface Fish implementieren.

Diese Java-Klassen sollen nicht-generisch sein. Die move()-Methode soll einfach einen String auf der Konsole ausgeben, wie sich dieses Tier bewegen würde. Mit der getName()-Methode soll ein kurzer Name, beispielsweise der Tierklasse, zurückgegeben werden.

Hinweis: Die mit default markierten Methoden in Fish, Mammal und Reptile brauchen Sie in Ihren Klassen nicht implementieren. Wir werden später im Semester noch über die sogenannten “Default-Methoden” sprechen.

A02.3: Generische Klassen (15%)

Um Gehege zu modellieren, erstellen Sie in eine generische Klasse Habitat mit einer Typ-Variablen. Stellen Sie durch geeignete Beschränkung der Typ-Variablen sicher, dass nur Gehege mit von Animal abgeleiteten Typen gebildet werden können.

Es sollen (mindestens) folgende Methoden existieren:

  • void add(Animal animal) zur Aufnahme eines Tieres in das Gehege
  • void remove(Animal animal) um ein Tier aus einem Gehege zu entfernen
  • String getName() um den Namen des Geheges zu bestimmen

Hinweis: Der Parametertyp Animal in den Methoden muss entsprechend angepasst werden.

Jedes einzelne Tier im Gehege kann maximal einmal vorkommen. Begründen Sie die Wahl der Datenstruktur.

Legen Sie in Ihrer main()-Methode mindestens zwei konkrete Gehege als Instanzen der neuen generischen Klasse Habitat an. Dabei sollen in diesen konkreten Gehegen nur jeweils verschiedene Tiere einer "Art" (beispielweise Löwen, Hamster, ...) vorkommen. Fügen Sie einige passende Tiere in die beiden Gehege ein.

A02.4: Generische Klassen reloaded (30%)

Für die Repräsentation eines Zoologischen Gartens mit mehreren verschiedenen Gehegen erstellen Sie nun eine generische Klasse Zoo mit einer Typ-Variablen. Stellen Sie durch geeignete Beschränkung der Typ-Variablen sicher, dass nur Zoos mit von Habitat abgeleiteten Typen gebildet werden können.

Ein Zoo soll (mindestens) folgende Methoden besitzen:

  • void build(Habitat habitat) zur Aufnahme eines neuen Geheges in den Zoo
  • void abandon(Habitat habitat) um ein Gehege aus dem Zoo zu entfernen
  • void visitAllHabitats() um die Gehege in der Reihenfolge des Hinzufügens zu besuchen (d.h. ihren Namen auf der Konsole auszugeben)

Hinweis: Der Parametertyp Habitat in den Methoden muss entsprechend angepasst werden.

Jedes Gehege gibt es pro Zoo nur maximal einmal, und die Reihenfolge des Errichtens definiert eine Ordnung auf den Gehegen. Begründen Sie die Wahl der Datenstruktur.

Legen Sie in Ihrer main()-Methode einen konkreten Zoo als Instanz der neuen generischen Klasse Zoo an. Dieser Zoo soll einige Gehege für verschiedene Tiere beinhalten.

A02.5: Ableiten nicht-generischer Klassen (20%)

Leiten Sie von Zoo eine nicht-generische Klasse Aquarium ab. Aquarien können nur mit Gehegen angelegt werden, deren Tiere vom Typ Fish (oder abgeleitet) sind.

Legen Sie in Ihrer main()-Methode ein konkretes Aquarium als Instanz der neuen nicht-generischen Klasse Aquarium an und gruppieren Sie darin verschiedene Fisch-"Gehege".

A02.6: DevDungeon (10%)

Klonen Sie das Projekt DevDungeon und laden Sie es in Ihrer IDE als Gradle-Projekt. Betrachten Sie das Sub-Projekt "devDungeon". Dies ist ein von einem Studierenden (@Flamtky) erstelltes Spiel mit mehreren Leveln, in denen Sie spielerisch verschiedene Aufgaben in-game und ex-game lösen müssen.

Starten Sie den DevDungeon mit ./gradlew devDungeon:runDevDungeon. Spielen Sie sich für diese Aufgabe durch das erste Level (Intro-Level) und machen Sie sich mit der Spielmechanik vertraut. Sie bekommen in jedem relevanten Übergang passende Hinweise; allgemein können Sie sich auch die kurze Anleitung "How to play" anschauen.

WICHTIG: Achten Sie bitte darauf, dass im Projektpfad keine Leerzeichen und keine Sonderzeichen (Umlaute o.ä.) vorkommen! Dies kann zu seltsamen Fehler führen. Bitte auch darauf achten, dass Sie als JDK ein Java SE 21 (LTS) verwenden.


  1. erst auf Code klicken und dann auf Download ZIP ↩︎

  2. Ok, wir machen hier Informatik. Vermutlich ist die Biologie nicht ganz korrekt ;-) ↩︎