Assoziation
Bisher standen in deinen Objekten nur Zahlen und Zeichenketten. Jetzt darf ein Objekt ein anderes Objekt kennen. Diese Beziehung zwischen zwei Klassen heißt Assoziation.
Ein Fahrrad hat Reifen
classDiagram
class Fahrrad {
-String marke
-int gaenge
+Fahrrad(String pMarke, int pGaenge)
+void setzeVorderreifen(Reifen pReifen)
+Reifen getVorderreifen()
+void schreibeInfos()
}
class Reifen {
-String hersteller
-double breite
+Reifen(String pHersteller, double pBreite)
+String getHersteller()
+double getBreite()
}
Fahrrad --> Reifen : vorderreifen
Der Pfeil bedeutet: Ein Fahrrad kennt einen Reifen. Die Beschriftung am Pfeil ist der Name des Attributs.
- Ein Attribut vom Typ einer anderen Klasse stellt die Assoziation her:
private Reifen vorderreifen; - Solange kein Objekt zugewiesen wurde, steht dort
null– das heißt „kein Objekt“. - Über das Attribut ruft man Methoden des anderen Objekts auf:
vorderreifen.getHersteller(). - Die Prüfung
if (vorderreifen == null)ist wichtig. Ohne sie stürzt das Programm ab, sobald kein Reifen montiert ist.
Hier ist == einmal richtig, obwohl wir bei Zeichenketten immer equals verlangt haben.
Erkläre, warum vorderreifen == null korrekt ist.
Auflösung
== vergleicht bei Objekten die Verweise. Und genau das wollen wir hier wissen: Zeigt das Attribut auf irgendein Objekt – oder auf gar keines?
equals würde nicht funktionieren: Man müsste dafür eine Methode auf einem Objekt aufrufen, das es womöglich gar nicht gibt.
Merke: == null ist die einzige Stelle, an der == bei Objekten die richtige Wahl ist.
Ein Objekt kennt mehrere
Ein Fahrrad hat zwei Reifen, ein Kurs viele Schüler. Für „mehrere“ nimmt man ein Feld.
classDiagram
class Kurs {
-String bezeichnung
-Schueler[] mitglieder
-int anzahl
+Kurs(String pBezeichnung, int pMaxGroesse)
+boolean nimmAuf(Schueler pSchueler)
+double durchschnitt()
+String besterName()
}
class Schueler {
-String name
-int punkte
+getName()
+getPunkte()
}
Kurs --> "0..*" Schueler : mitglieder
Die Beschriftung 0..* am Pfeil heißt Kardinalität: Ein Kurs kennt beliebig viele Schüler – auch keinen.
Aufgabe: Der Kurs
Setze die Klasse Kurs so um, dass alle Tests grün werden.
Das ist die Aufgabe aus Kapitel 5 – nur dass Name und Punktzahl jetzt nicht mehr auseinanderlaufen können.
Tipp 1: Warum ein zusätzliches Attribut anzahl?
Das Feld hat von Anfang an pMaxGroesse Plätze – die meisten davon leer, also null. mitglieder.length sagt dir also nur, wie viele Plätze es gibt, nicht wie viele belegt sind.
Deshalb zählst du in anzahl mit, wie weit das Feld gefüllt ist. Alle Schleifen laufen dann bis anzahl, nicht bis mitglieder.length.
Tipp 2: Aufnehmen
if (anzahl < mitglieder.length) {
mitglieder[anzahl] = pSchueler;
anzahl++;
return true;
}
return false;
Der neue Schüler kommt genau auf den ersten freien Platz – und dessen Index ist die bisherige Anzahl.
Tipp 3: besterName
Merke dir wie in Kapitel 5 den Index des Besten, nicht die Punktzahl. Nur so kommst du am Ende an den Namen.
Und denke an den Sonderfall: Bei anzahl == 0 darfst du gar nicht erst auf mitglieder[0] zugreifen.
Aufgabe 2: Modellieren
Modelliere eine Bibliothek.
a) Ermittle die beteiligten Klassen und ihre Beziehungen. Wer kennt wen?
b) Zeichne das Diagramm mit Attributen, Methoden und Kardinalitäten.
c) Setze mindestens zwei der Klassen um.
Denk darüber nach: Kennt ein Buch seinen Ausleiher, oder kennt eine Person ihre ausgeliehenen Bücher? Oder beides? Begründe deine Entscheidung.
Zusatzaufgabe
Ein Fahrrad hat zwei Reifen: einen vorne und einen hinten.
a) Erweitere Fahrrad entsprechend.
b) Was passiert, wenn du dasselbe Reifen-Objekt vorne und hinten montierst? Probiere es aus, ändere über eine Setter-Methode die Breite des Vorderreifens und schau, was mit dem Hinterreifen passiert.
c) Erkläre die Beobachtung. Ist das ein Fehler in deinem Programm oder eine Eigenschaft von Objektvariablen?