MINT lernen

Übung — AFB I (Reproduzieren)

Zehn Standardaufgaben zur objektorientierten Modellierung: Diagramme lesen, Zustände verfolgen, Kardinalitäten und Vererbung ablesen.

Dein Fortschritt:
0 / 0 Aufgaben
1

Aufgabenblock — AFB I

Zehn Standardaufgaben quer durch das ganze Kapitel — bunt gemischt statt nach Unterkapiteln sortiert: Klassenkarten und Objektkarten lesen, Zustände nach Methodenaufrufen angeben, Kardinalitäten und Vererbungshierarchien ablesen, Listen und überschriebene Methoden verfolgen. Das sind die sicheren Punkte in jeder Klausur zur Objektorientierung.

A1
Klassenkarte lesen: Song
AFB I

Eine Playlist-App verwendet die folgende Klasse. Entnehmen Sie der Klassenkarte, wie viele Parameter der Konstruktor hat und wie viele der Methoden Anfragen bzw. Aufträge sind.

Song
  • - titel: Zeichenkette
  • - interpret: Zeichenkette
  • - dauerSek: Ganzzahl
  • - favorit: Wahrheitswert
  • c Song(titel: Zeichenkette, interpret: Zeichenkette, dauerSek: Ganzzahl)
  • + getTitel(): Zeichenkette
  • + getDauerSek(): Ganzzahl
  • + istFavorit(): Wahrheitswert
  • + markieren()
  • + setDauerSek(dauerSek: Ganzzahl)
Ansatz: Parameter stehen im Konstruktor in der Klammer, jeweils als name: Typ, durch Kommas getrennt.
Unterscheidung: Eine Anfrage liefert einen Wert zurück — in der Karte steht dann hinter der Klammer ein Rückgabetyp. Ein Auftrag ändert den Zustand und hat keinen Rückgabetyp.
Kontrolle: Der Konstruktor ist weder Anfrage noch Auftrag. Zähle also nur die fünf Zeilen mit +.
Vollständige Lösung

Der Konstruktor c Song(titel, interpret, dauerSek) hat 3 Parameter. favorit wird nicht übergeben, sondern im Konstruktor auf false gesetzt.

Anfragen (3): getTitel(): Zeichenkette, getDauerSek(): Ganzzahl, istFavorit(): Wahrheitswert — sie haben einen Rückgabetyp.
Aufträge (2): markieren() und setDauerSek(dauerSek: Ganzzahl) — kein Rückgabetyp, sie ändern den Zustand.

Beachte: Für interpret gibt es keinen Getter. Das Attribut ist privat und damit von außen weder lesbar noch änderbar — ob das so gewollt ist, müsste man im Entwurf klären.

A2
Kardinalitäten lesen: Onlineshop
AFB I

Ein Onlineshop ist so modelliert:

Kunde
  • - name: Zeichenkette
  • - bestellungen: DynArray<Bestellung>
bestellungen*
Bestellung
  • - datum: Zeichenkette
  • - positionen: DynArray<Position>
positionen1..*
Position
  • - menge: Ganzzahl
  • - artikel: Artikel
artikel1
Artikel
  • - preis: Fließkommazahl

Nennen Sie die gesuchten Anzahlen.

Ansatz: Die Zahl am Linienende sagt, wie viele Objekte ein Objekt am Linienanfang kennt.
Mindestens: 1..* heißt „mindestens eins, nach oben offen“.
Kontrolle: Referenzattribute haben den Typ einer anderen Klasse oder einer Liste davon — zähle die Klassen, von denen ein Pfeil ausgeht.
Vollständige Lösung

Eine Position kennt genau 1 Artikel. Eine Bestellung hat mindestens 1 Position (1..*). Referenzattribute haben Kunde (bestellungen), Bestellung (positionen) und Position (artikel) — also 3 Klassen; Artikel kennt niemanden.

Beachte: Das Diagramm sagt nicht, zu wie vielen Bestellungen ein Kunde-Objekt gehört — Rückrichtungen sind nicht modelliert.

A3
Zustand nach Methodenaufrufen: Kaffeeautomat
AFB I

Die Methode kaffeeZubereiten() verbraucht 14 g Bohnen und erhöht becher um 1 — aber nur, wenn noch mindestens 14 g vorhanden sind. auffuellen(gramm) erhöht den Bohnenvorrat.

Kaffeeautomat k = new Kaffeeautomat(40);
k.kaffeeZubereiten();
k.kaffeeZubereiten();
k.kaffeeZubereiten();
k.auffuellen(30);
k.kaffeeZubereiten();

Geben Sie die Attributwerte des Objekts k nach allen Aufrufen an.

g
Ansatz: Lege eine kleine Tabelle an: Zeile für Zeile den Wert von bohnenGramm und becher fortschreiben.
Stolperstelle: Nach zwei Kaffees sind noch 12 g übrig. Was passiert beim dritten Aufruf, wenn die Bedingung bohnenGramm >= 14 nicht erfüllt ist?
Vollständige Lösung

Die Methode im Quelltext:

public class Kaffeeautomat {
    private int bohnenGramm;
    private int becher;

    public Kaffeeautomat(int bohnenGramm) {
        this.bohnenGramm = bohnenGramm;
        becher = 0;
    }

    public void kaffeeZubereiten() {
        if (bohnenGramm >= 14) {
            bohnenGramm = bohnenGramm - 14;
            becher = becher + 1;
        }
    }

    public void auffuellen(int gramm) {
        bohnenGramm = bohnenGramm + gramm;
    }

    public int getBohnenGramm() {
        return bohnenGramm;
    }

    public int getBecher() {
        return becher;
    }
}

Ablauf: 40 g / 0 → 26 g / 1 → 12 g / 2 → dritter Aufruf: 12 < 14, nichts passiert → auffüllen: 42 g / 2 → 28 g / 3.

k: Kaffeeautomat
  • bohnenGramm = 28
  • becher = 3

Typischer Fehler: 4 Becher und 0 g — dann wurde die Bedingung im dritten Aufruf übersehen.

k: Kaffeeautomat
  • bohnenGramm = 40
  • becher = 0
Objektkarte direkt nach dem Konstruktor
A4
Vererbung lesen: Streamingdienst
AFB I

Ein Streamingdienst verwaltet seine Inhalte so:

Inhalt
  • - titel: Zeichenkette
  • - jahr: Ganzzahl
  • + abspielen()
Film
  • - laufzeit: Ganzzahl
  • + getLaufzeit(): Ganzzahl
Serie
  • - staffeln: Ganzzahl
  • - folgenProStaffel: Ganzzahl
  • + folgenGesamt(): Ganzzahl

Beschreiben Sie die dargestellte Beziehung zwischen den Klassen und geben Sie die Anzahlen an.

Ansatz: Das hohle Dreieck zeigt zur Oberklasse. Was dort steht, besitzt jede Unterklasse ebenfalls.
Geschwister: Film und Serie erben nur von Inhalt — nicht voneinander.
Vollständige Lösung

Film und Serie sind Unterklassen von Inhalt: Ein Film ist ein Inhalt, eine Serie ebenso. Sie erben titel, jahr und abspielen() und ergänzen eigene Elemente.

Ein Serie-Objekt hat 4 Attribute: titel, jahr (geerbt), staffeln, folgenProStaffel. Ein Film-Objekt kann 2 öffentliche Methoden ausführen: abspielen() (geerbt) und getLaufzeit(); folgenGesamt() gehört nur der Serie.

A5
Konstruktor, Getter und Setter: Pflanze
AFB I

Ein Gewächshaus-Programm verwaltet Pflanzen. Die Höhe soll nur Werte von 0 bis 500 cm annehmen; ungültige Werte werden ignoriert. Nach dem Erzeugen ist die Höhe 0.

Pflanze
  • - art: Zeichenkette
  • - hoeheCm: Ganzzahl
  • c Pflanze(art: Zeichenkette)
  • + getHoeheCm(): Ganzzahl
  • + setHoeheCm(hoeheCm: Ganzzahl)

Stellen Sie die Klasse vollständig als Java-Quelltext dar.

Ansatz: Reihenfolge im Klassenrumpf: Attribute (private), Konstruktor (ohne Rückgabetyp, auch ohne void), dann die Methoden.
Setter: Der Parameter heißt genauso wie das Attribut. Ohne this. würdest du nur den Parameter mit sich selbst überschreiben. Die Zuweisung steht in einem if mit der Bereichsprüfung.
Vollständige Lösung
public class Pflanze {
    private String art;
    private int hoeheCm;

    public Pflanze(String art) {
        this.art = art;
        hoeheCm = 0;
    }

    public int getHoeheCm() {
        return hoeheCm;
    }

    public void setHoeheCm(int hoeheCm) {
        if (hoeheCm >= 0 && hoeheCm <= 500) {
            this.hoeheCm = hoeheCm;
        }
    }
}

Häufige Fehler: public void Pflanze(...) ist kein Konstruktor, sondern eine Methode; hoeheCm = hoeheCm; ohne this ändert das Attribut nicht; ein Getter ohne return kompiliert nicht.

A6
Liste verfolgen: Wartezimmer
AFB I

Eine Arztpraxis verwaltet ihr Wartezimmer mit einer dynamischen Reihung. Wenden Sie die Anweisungen der Reihe nach an.

ArrayList<Patient> warte = new ArrayList<Patient>();
warte.add(new Patient("Ali"));
warte.add(new Patient("Bea"));
warte.add(new Patient("Cem"));
warte.remove(0);
warte.add(new Patient("Dan"));
Patient p = warte.get(1);
Ansatz: Schreibe die Liste nach jeder Zeile als [ … ] auf.
remove: remove(0) entfernt das Element an Index 0 — alle folgenden rücken eine Stelle nach vorn.
Vollständige Lösung

[Ali] → [Ali, Bea] → [Ali, Bea, Cem] → nach remove(0): [Bea, Cem] → [Bea, Cem, Dan]. Also size() = 3, Dan steht an Index 2, und p verweist auf Cem. Im Abitur-Pseudocode heißen die Operationen append, delete, getItem und getLength.

A7
Vom Quelltext zur Klassenkarte: Handyvertrag
AFB I

Gegeben ist der Quelltext einer Klasse aus der Kundenverwaltung eines Mobilfunkanbieters.

public class Handyvertrag {
    private String nummer;
    private int datenvolumenMB;
    private int verbrauchtMB;
    private boolean gesperrt;

    public Handyvertrag(String nummer, int datenvolumenMB) {
        this.nummer = nummer;
        this.datenvolumenMB = datenvolumenMB;
        verbrauchtMB = 0;
        gesperrt = false;
    }

    public int getRestMB() {
        return datenvolumenMB - verbrauchtMB;
    }

    public void surfen(int mb) {
        if (!gesperrt) {
            verbrauchtMB = verbrauchtMB + mb;
            pruefen();
        }
    }

    public boolean istGesperrt() {
        return gesperrt;
    }

    private void pruefen() {
        if (verbrauchtMB >= datenvolumenMB) {
            gesperrt = true;
        }
    }
}

Zeichnen Sie die zugehörige Klassenkarte in der Notation der Ergänzenden Hinweise.

Ansatz: Drei Felder: Name — Attribute — Konstruktor und Methoden. private wird zu -, public zu +.
Typen übersetzen: int → Ganzzahl, String → Zeichenkette, boolean → Wahrheitswert. Der Konstruktor bekommt ein vorangestelltes c; void wird einfach weggelassen.
Achtung: Es gibt eine private Methode — auch sie gehört in die Karte. Und getRestMB() hat kein gleichnamiges Attribut: Der Wert wird berechnet.
Vollständige Lösung
Handyvertrag
  • - nummer: Zeichenkette
  • - datenvolumenMB: Ganzzahl
  • - verbrauchtMB: Ganzzahl
  • - gesperrt: Wahrheitswert
  • c Handyvertrag(nummer: Zeichenkette, datenvolumenMB: Ganzzahl)
  • + getRestMB(): Ganzzahl
  • + surfen(mb: Ganzzahl)
  • + istGesperrt(): Wahrheitswert
  • - pruefen()

Nur die Attribute kommen ins mittlere Feld — lokale Variablen oder berechnete Werte wie der Rest nicht. pruefen() ist eine private Hilfsmethode und wird mit - notiert.

A8
Überschreiben verfolgen: Lampe und Dimmer
AFB I

Gegeben sind zwei Klassen:

public class Lampe {
    protected int helligkeit;
    public Lampe() { helligkeit = 50; }
    public void heller() { helligkeit = helligkeit + 10; }
    public int getHelligkeit() { return helligkeit; }
}
public class Dimmer extends Lampe {
    @Override
    public void heller() { helligkeit = helligkeit + 5; }
}
Lampe a = new Lampe();
Lampe b = new Dimmer();
a.heller();
b.heller();
b.heller();

Berechnen Sie die Helligkeiten am Ende.

Ansatz: Welcher Konstruktor setzt beim Dimmer den Startwert?
Methode: b hat den Typ Lampe, zeigt aber auf einen Dimmer — es läuft die Methode des Objekts.
Vollständige Lösung

a: 50 + 10 = 60. b: Der Dimmer hat keinen eigenen Konstruktor, deshalb läuft der Konstruktor von Lampe (Startwert 50). Beide Aufrufe von heller() führen die überschreibende Methode des Dimmers aus: 50 + 5 + 5 = 60. Wer 70 erhält, hat die Methode der Variable statt der des Objekts genommen.

A9
Referenz oder Wert? Fitnesstracker
AFB I

Die Klasse Tracker hat ein Attribut schritte (Start 0), eine Methode schritteAddieren(anzahl) und den Getter getSchritte().

Tracker a = new Tracker("Mia");
a.schritteAddieren(4200);
Tracker b = a;
b.schritteAddieren(800);
int s = a.getSchritte();
s = s + 1000;
Tracker c = new Tracker("Mia");
c.schritteAddieren(s);

Bestimmen Sie die Rückgaben von a.getSchritte() und c.getSchritte() nach dem letzten Befehl sowie die Anzahl der erzeugten Tracker-Objekte.

Ansatz: Zähle die new. Jede Variable vom Typ Tracker ist nur ein Verweis auf ein Objekt.
Alias: Nach b = a zeigen beide Variablen auf dasselbe Objekt. s ist dagegen eine int-Variable: Sie enthält eine Kopie des Werts.
Vollständige Lösung

Es gibt 2 Objekte (zweimal new). a und b verweisen auf dasselbe Objekt: 4200 + 800 = 5000. s erhält eine Kopie dieses Werts; s = s + 1000; ändert nur s (6000), nicht das Objekt. Das zweite Objekt c hat trotz gleichem Namen „Mia“ eine eigene Identität und bekommt 6000 Schritte.

a: Tracker
  • name = "Mia"
  • schritte = 5000
c: Tracker
  • name = "Mia"
  • schritte = 6000

Die linke Karte ist das Objekt, auf das a und b verweisen.

A10
Phasen im Softwareprojekt: Klassenfahrt-App
AFB I

Ein Kurs entwickelt im Team eine App, mit der sich Teilnehmende einer Klassenfahrt in Zimmer eintragen. Ordnen Sie jede Tätigkeit einer Projektphase (Analyse, Entwurf, Implementierung, Test) zu.

  1. Mit der Lehrkraft wird geklärt, dass ein Zimmer höchstens vier Betten hat und Jungen und Mädchen getrennt wohnen.
  2. Das Team legt fest: Die Klasse Zimmer bekommt die Methode + belegen(t: Teilnehmer): Wahrheitswert.
  3. Es wird notiert: „Ein fünfter Teilnehmer in einem vollen Viererzimmer → belegen liefert false.“
  4. Jonas schreibt die Methode belegen in Java.
  5. Die Anforderungen werden in einem Pflichtenheft zusammengefasst.
  6. Das Klassendiagramm wird im Team abgestimmt, bevor jemand programmiert.
Ansatz: Frage dich bei jeder Tätigkeit: Geht es um was das Programm können soll (Analyse), wie es aufgebaut ist (Entwurf), um Quelltext (Implementierung) oder um das Prüfen (Test)?
Stolperstelle c: Testfälle werden sinnvollerweise schon vor dem Programmieren formuliert — sie gehören trotzdem zur Testphase.
Vollständige Lösung

a) Analyse — fachliche Anforderung klären. b) Entwurf — Methodensignatur festlegen. c) Test — Testfall mit erwartetem Ergebnis. d) Implementierung. e) Analyse — das Pflichtenheft ist ihr Ergebnis. f) Entwurf — das abgestimmte Klassendiagramm ist die Schnittstelle, an die sich alle beim Programmieren halten.