MINT lernen

Übungen: Assoziationen zwischen Klassen

Ein Fahrradverleih, ein Zoo und eine Playlist: Wer kennt hier wen — und wie viele davon?

Dein Fortschritt:
0 / 0 Aufgaben
1

Übungsaufgaben

Zehn Übungen zum Klicken, Ziehen und Knobeln — von AFB I bis AFB III. Jede Übung gibt dir sofort Rückmeldung; wenn du hängst, helfen dir die gestuften Tipps.

A1
Fahrradverleih im Diagramm
AFB I

Ein Fahrradverleih wird so modelliert. Geben Sie alle Aussagen an, die zum Klassendiagramm passen.

Station
  • - ort: Zeichenkette
  • - raeder: Reihung von Fahrrad
  • + abstellen(f: Fahrrad): Wahrheitswert
raeder0..12
Fahrrad
  • - nummer: Ganzzahl
  • - ausleiher: Kunde
  • + zurueckgeben()
ausleiher0..1
Kunde
  • - name: Zeichenkette
  • + getName(): Zeichenkette
Mehrere Antworten sind richtig. Markiere alle zutreffenden und klicke dann auf „Auswahl prüfen“.
0..12 ist eine Obergrenze, keine feste Anzahl — eine Station kann auch leer sein. 0..1 an der Kunden-Seite heißt: kein oder ein Ausleiher. Die Pfeile zeigen nach rechts; deshalb weiß ein Kunde nichts von seinem Fahrrad. Soll er es kennen, bräuchte die Linie auch zur anderen Seite eine Navigationsrichtung.
Ansatz: Lies jede Zahl als „ein Objekt links kennt so viele Objekte rechts“.
Weiter: Die Pfeilspitze zeigt die Richtung: Nur die Klasse am Linienanfang bekommt ein Attribut.
A2
Stimmt's? — Der Zoo
AFB I

Entnehmen Sie dem Klassendiagramm eines Zoos, welche Aussagen stimmen.

Gehege
  • - nummer: Ganzzahl
  • - tiere: DynArray<Tier>
  • + einsetzen(t: Tier)
tiere*
Tier
  • - art: Zeichenkette
  • - pfleger: Tierpfleger
  • + getPfleger(): Tierpfleger
pfleger1
Tierpfleger
  • - name: Zeichenkette
  • + getName(): Zeichenkette
5 Aussagen nacheinander. Eine falsche Einschätzung reicht — dann startest du die Serie mit „Neue Runde“ neu.
Aussage 1 von 5

Eine Assoziation liest man immer mit der Richtung und der Zahl am Ende: „Ein Gehege kennt * Tiere“, „ein Tier kennt 1 Tierpfleger“. Was nicht im Diagramm steht (Pfleger → Tiere), gibt es im Programm auch nicht — man erreicht es höchstens über eine Kette von Aufrufen.
Ansatz: Lies jede Linie in Pfeilrichtung als Satz: „Ein … kennt … “.
Weiter: Eine Klasse bekommt nur für ausgehende Pfeile ein Attribut. Rückwärts gibt es keinen Weg.
A3
Welches Attribut passt?
AFB I

Ordnen Sie jeder Anforderung das Attribut zu, das sie in Java umsetzt.

Ansatz: Suche in jedem Satz das Mengenwort: „genau eine“, „höchstens“, „beliebig viele“.
Weiter: Feste Obergrenze → Reihung mit dieser Länge, keine Obergrenze → dynamische Reihung.
A4
Eine Playlist kennt ihre Songs
AFB II

Im Klassendiagramm steht Playlist ——songs——> * Song; Song hat die Methode getDauer(): Ganzzahl (Sekunden). Implementieren Sie die Klasse, indem Sie die Lücken füllen — drei Bausteine bleiben übrig.

Wort anklicken, dann Lücke anklicken (oder umgekehrt) — mit Tab und Enter geht es genauso. Ein Klick auf eine gefüllte Lücke legt das Wort zurück.

public class Playlist {
    private String name;
    private songs;
    public Playlist(String name) {
        this.name = name;
        songs = ArrayList<Song>();
    }
    public void hinzufuegen(Song s) { songs.(s); }
    public int getLaenge() {
        int summe = 0;
        for (int i = 0; i < songs.(); i++) {
            summe = summe + songs.(i).getDauer();
        }
        return summe;
    }
}

Song[] hätte eine feste Länge — für * braucht man die dynamische Reihung. length gibt es nur bei Reihungen, bei der ArrayList heißt es size(). append ist der Name aus dem Abitur-DynArray; in Java heißt die Operation add. Ohne new im Konstruktor wäre songs null.
Ansatz: Welcher Typ passt zu „beliebig viele“ — und wie heißen die Operationen der Java-Liste?
Weiter: Die Liste muss im Konstruktor erzeugt werden. Anzahl: size(), Zugriff: get(i), Anhängen: add(x).
A5
Ein Song in zwei Playlists
AFB II Mix

Mit der Klasse Playlist aus A4 und Song (mit setDauer(d: Ganzzahl)) läuft das folgende Programm. Bestimmen Sie die Werte — denk an Referenzen aus 4.2.3.

Song a = new Song("Lotus", 200);
Playlist p = new Playlist("Sport");
Playlist q = new Playlist("Chill");
p.hinzufuegen(a);
q.hinzufuegen(a);
p.hinzufuegen(new Song("Echo", 180));
a.setDauer(240);
Arbeite die Kette Schritt für Schritt ab: Erst wenn ein Schritt stimmt, wird der nächste freigeschaltet. Enter prüft.
  1. Wie viele Song-Objekte gibt es? Objekte
  2. p.getLaenge() s
  3. q.getLaenge() s
  4. Nach zusätzlich p = q; liefert p.getLaenge() s
Beide Listen speichern eine Referenz auf dasselbe Objekt a — es gibt nur zwei Song-Objekte. setDauer(240) ändert dieses eine Objekt, also sehen es beide Playlists: p = 240 + 180 = 420, q = 240. p = q kopiert nur die Referenz auf die Playlist; danach zeigen p und q auf dieselbe Liste (240), die „Sport“-Liste ist nicht mehr erreichbar.
Ansatz: Zähle die new Song(…)-Aufrufe. hinzufuegen kopiert kein Objekt.
Weiter: Wird ein Objekt über eine Referenz geändert, sehen das alle, die dieselbe Referenz gespeichert haben.
A6
Rückgabe in beide Richtungen
AFB II

Kunde und Fahrrad kennen sich jetzt gegenseitig (0..1 auf beiden Seiten). Bei der Rückgabe müssen beide Referenzen gelöscht werden. Erstellen Sie die Methode der Klasse Fahrrad, indem Sie die Zeilen ordnen.

Ziehe die Karten in die richtige Reihenfolge — mit der Tastatur: ↑/↓ verschiebt, Shift+↑/↓ wechselt nur den Fokus.
1public void zurueckgeben() {
2if (ausleiher != null) {
3ausleiher.setRad(null);
4ausleiher = null;
5} — Ende von if
6} — Ende der Methode
Die Reihenfolge der beiden Zuweisungen ist nicht egal: Setzt man zuerst ausleiher = null, führt ausleiher.setRad(null) zu einer NullPointerException — der Kunde behielte das Rad. Bei Beziehungen in beide Richtungen muss eine Methode immer beide Seiten konsistent halten.
Ansatz: Solange ausleiher noch auf den Kunden zeigt, kann man ihm etwas mitteilen.
Weiter: Erst dem Kunden sagen, dass er kein Rad mehr hat, dann die eigene Referenz löschen.
A7
Mengenwörter übersetzen
AFB II

Analysieren Sie jede Anforderung: Welche Kardinalität steht an der Seite der gezählten (fett gedruckten) Klasse?

Ziehe jede Karte in den passenden Korb — oder wähle sie mit Enter aus und drücke dann die Ziffer des Korbs (0 legt sie zurück).
11
20..1
3*
41..*
„Genau ein“ → 1, „höchstens ein“ oder „frei oder …“ → 0..1, „beliebig viele, auch keine“ → *, „mindestens ein“ → 1..*. Bei 1..* reicht in Java ebenfalls eine ArrayList — die Mindestzahl muss dann der Konstruktor oder eine Prüfung sicherstellen.
Ansatz: Achte auf die Wörter „genau“, „höchstens“, „mindestens“ und „auch keine“.
Weiter: „Frei oder belegt“ bedeutet: null oder eins.
A8
Fehlersuche: Die Arztpraxis
AFB III

Eine Praxis kennt beliebig viele Patienten (Praxis ——patienten——> * Patient). Überprüfen Sie die Implementierung: Drei Zeilen führen zu einem Übersetzungsfehler, einem Laufzeitfehler oder einem falschen Ergebnis.

In diesem Text stecken Fehler. Klicke genau die falschen Zeilen an — die richtigen musst du stehen lassen.
Der leere Konstruktor ist der gefährlichste Fehler, weil der Compiler ihn nicht bemerkt: Erst der erste Aufruf von aufnehmen endet mit einer NullPointerException. length scheitert schon beim Übersetzen, get(1) liefert still den zweiten Patienten — oder eine Exception, wenn nur einer da ist.
Ansatz: Prüfe für jede Zeile: Wird die Liste erzeugt? Heißen die Methoden so wie bei ArrayList?
Weiter: Denk an die drei Fehlerarten: fehlendes new, Reihungs-Schreibweise statt Listen-Methode, Index ab 0.
A9
Einen freien Platz finden
AFB III

Die Station aus A1 speichert ihre Räder in private Fahrrad[] raeder = new Fahrrad[12]; (Kardinalität 0..12). Erweitern Sie die Klasse um eine Methode, die ein Rad auf dem ersten freien Platz abstellt und meldet, ob das geklappt hat.

Wähle in jedem Menü den passenden Eintrag und prüfe dann alle auf einmal.
public boolean abstellen(Fahrrad f) {
    for (int i = 0; i < ; i++) {
        if (raeder[i] ) {
            raeder[i] = ;
            return ;
        }
    }
    return ;
}
Bei einer Reihung fester Länge heißen freie Plätze null. Man sucht den ersten solchen Platz, trägt die Referenz ein und bricht sofort mit true ab. Erst wenn die Schleife ohne Treffer durchläuft, sind alle zwölf Plätze belegt → false. raeder.size() gibt es bei Reihungen nicht, und 12 - 1 würde den letzten Platz auslassen.
Ansatz: Freie Plätze einer Reihung von Objekten enthalten null.
Weiter: Nach dem Eintragen sofort zurückkehren — sonst füllt die Schleife alle freien Plätze mit demselben Rad.
A10
Trickaufgabe: Viermal Nova?
AFB III Trick

Gegeben ist die Klasse Song aus A5. Ermitteln Sie die Summe der Dauern aller Einträge von mix am Ende des Programms.

ArrayList<Song> mix = new ArrayList<Song>();
Song s = new Song("Nova", 150);
mix.add(s);
mix.add(s);
s = new Song("Orbit", 210);
mix.add(s);
mix.add(mix.get(0));
mix.get(1).setDauer(100);
Überlege selbst und trage das Ergebnis ein — Enter prüft direkt.
Die Liste hat vier Einträge, aber nur zwei Song-Objekte: Index 0, 1 und 3 zeigen auf „Nova“, Index 2 auf „Orbit“. s = new Song(…) ändert nur die Variable s, nicht die schon gespeicherten Referenzen. mix.get(1).setDauer(100) ändert das Nova-Objekt — also alle drei Einträge: 3 · 100 + 210 = 510. Wer 610 hat, hat nur einen Eintrag geändert.
Ansatz: Zeichne die Liste als vier Kästchen mit Pfeilen auf die Objekte.
Weiter: Wie viele verschiedene Objekte gibt es — und auf welches zeigt Index 1?