MINT lernen

Abituraufgaben: Eine Klasse implementieren

Zwei Abituraufgaben mit Hinweisen und Erwartungshorizont: Klassen nach Diagramm in Java implementieren – Gewächshaus und Kfz-Werkstatt.

Dein Fortschritt:
0 / 0 Aufgaben
1

Pflanzen im Schulgewächshaus

AFB I–II

Die Garten-AG simuliert das Wachstum ihrer Pflanzen im Schulgewächshaus. Jede Pflanze hat einen Wasserstand in Prozent (0 bis 100) und eine Höhe in Zentimetern. Je nach Art verbraucht sie pro Tag unterschiedlich viel Wasser. Eine neue Pflanze startet mit einem Wasserstand von 50 und einer Höhe von 5,0 cm.

Die Methoden sollen sich so verhalten: giessen(menge) erhöht den Wasserstand um die angegebene Menge, jedoch höchstens auf 100; nicht positive Mengen bleiben ohne Wirkung. tagVergeht() verringert den Wasserstand um den Tagesverbrauch, jedoch nicht unter 0. Liegt der Wasserstand danach bei mindestens 30, wächst die Pflanze um 0,5 cm. brauchtWasser() liefert genau dann true, wenn der Wasserstand unter 30 liegt.

Material 1: Klassenkarte und begonnene Implementierung
Pflanze
  • - name: Zeichenkette
  • - wasserstand: Ganzzahl
  • - hoehe: Fließkommazahl
  • - verbrauch: Ganzzahl
  • c Pflanze(name: Zeichenkette, verbrauch: Ganzzahl)
  • + giessen(menge: Ganzzahl)
  • + tagVergeht()
  • + getWasserstand(): Ganzzahl
  • + getHoehe(): Fließkommazahl
  • + brauchtWasser(): Wahrheitswert
public class Pflanze {
    private String name;
    private int wasserstand;
    private double hoehe;
    private int verbrauch;

    public Pflanze(String name, int verbrauch) {
        this.name = name;
        this.verbrauch = verbrauch;
        wasserstand = 50;
        hoehe = 5.0;
    }

    // hier fehlen die Methoden
}
Attribute und Konstruktor sind bereits implementiert.
Material 2: Testprogramm und Konstruktor-Entwurf eines Mitschülers
Pflanze p = new Pflanze("Basilikum", 15);
p.tagVergeht();
p.tagVergeht();
System.out.println(p.brauchtWasser());
p.giessen(90);
p.tagVergeht();
System.out.println(p.getWasserstand() + " / " + p.getHoehe());
// Entwurf von Ben (Ausschnitt)
public void Pflanze(String name, int verbrauch) {
    name = name;
    verbrauch = verbrauch;
    wasserstand = 50;
    hoehe = 5.0;
}

public int getWasserstand() {
    wasserstand;
}
Oben: Test der AG. Unten: Bens eigener Versuch, die Klasse zu schreiben; markierte Stellen sind fehlerhaft.
  1. Ergänzen Sie die Klasse aus Material 1 um die fünf im Diagramm angegebenen Methoden gemäß der Beschreibung.
  2. Ermitteln Sie die beiden Ausgaben des Testprogramms aus Material 2. Notieren Sie dazu nach jedem Aufruf den Wasserstand und die Höhe.
  3. Erklären Sie für jede markierte Stelle in Bens Entwurf, warum sie fehlerhaft ist und welche Folge sie hat, und geben Sie jeweils eine Korrektur an.

Hinweise

Hinweis zu Aufgabe a)
Übersetze jede Zeile der Klassenkarte: kein Rückgabetyp im Diagramm → void; Ganzzahl → int, Wahrheitswert → boolean. Für „höchstens 100“ bzw. „nicht unter 0“ brauchst du nach der Rechnung eine if-Abfrage. Anfragen enden mit return.„Ergänzen“ heißt: die vorgegebene Lösung beibehalten und nach den Vorgaben erweitern – Attribute und Konstruktor nicht neu schreiben.
Hinweis zu Aufgabe b)
Starte bei Wasserstand 50 und Höhe 5,0. Achte bei tagVergeht() auf die Reihenfolge: erst Wasser abziehen, dann prüfen, ob gewachsen wird. Und beim Gießen: Gibt es eine Obergrenze?
Hinweis zu Aufgabe c)
Drei verschiedene Fehlerarten: Was unterscheidet einen Konstruktor von einer Methode? Welche Variable ist gemeint, wenn Parameter und Attribut gleich heißen? Was muss eine Methode mit Rückgabetyp int immer enthalten?„Erklären“ heißt: den Fehler auf die zugrunde liegende Regel von Java zurückführen, nicht nur die Korrektur hinschreiben.

Erwartungshorizont

Erwartungshorizont zu Aufgabe a)
public void giessen(int menge) {
    if (menge > 0) {
        wasserstand = wasserstand + menge;
        if (wasserstand > 100) {
            wasserstand = 100;
        }
    }
}

public void tagVergeht() {
    wasserstand = wasserstand - verbrauch;
    if (wasserstand < 0) {
        wasserstand = 0;
    }
    if (wasserstand >= 30) {
        hoehe = hoehe + 0.5;
    }
}

public int getWasserstand() {
    return wasserstand;
}

public double getHoehe() {
    return hoehe;
}

public boolean brauchtWasser() {
    return wasserstand < 30;
}

Bewertet werden korrekte Methodenköpfe (Sichtbarkeit, Rückgabetyp, Parameter), die Begrenzung auf 0 bis 100, die Wachstumsbedingung nach dem Abziehen und die return-Anweisungen. Gleichwertige Lösungen (z. B. Math.min oder if (…) { return true; } else { return false; }) sind zu akzeptieren.

Erwartungshorizont zu Aufgabe b)

Start: wasserstand = 50, hoehe = 5.0

1. tagVergeht(): 50 − 15 = 35 ≥ 30 → hoehe = 5.5
2. tagVergeht(): 35 − 15 = 20 < 30 → hoehe bleibt 5.5
Ausgabe 1: true (20 < 30)
3. giessen(90): 20 + 90 = 110 → begrenzt auf 100
4. tagVergeht(): 100 − 15 = 85 → hoehe = 6.0

Ausgabe 2: 85 / 6.0

Häufiger Fehler: Die Begrenzung auf 100 übersehen (Ergebnis dann 95).

Erwartungshorizont zu Aufgabe c)

void im Konstruktor: Ein Konstruktor hat keinen Rückgabetyp. Mit void entsteht eine gewöhnliche Methode, die zufällig wie die Klasse heißt. Java stellt dann nur den parameterlosen Standardkonstruktor bereit, und new Pflanze("Basilikum", 15) lässt sich nicht übersetzen. Korrektur: public Pflanze(String name, int verbrauch).

name = name; und verbrauch = verbrauch;: Der Parameter überdeckt das gleichnamige Attribut; beide Seiten bezeichnen den Parameter, er wird sich selbst zugewiesen. Die Attribute behalten ihre Standardwerte (null bzw. 0) – die Pflanze verbraucht dann nie Wasser. Korrektur: this.name = name; und this.verbrauch = verbrauch;.

wasserstand;: Eine Methode mit Rückgabetyp int muss einen Wert mit return zurückgeben; die bloße Nennung der Variablen ist keine gültige Anweisung, der Compiler meldet einen Fehler. Korrektur: return wasserstand;.

2

Reparaturaufträge in der Kfz-Werkstatt

AFB II–III

Die Kfz-Werkstatt Kemper ersetzt ihre Auftragszettel durch ein Programm. Ein Reparaturauftrag wird bei der Fahrzeugannahme mit dem Kennzeichen und einer kurzen Fehlerbeschreibung angelegt und hat dann den Status „angenommen“. Sobald ein Mechaniker mit der Arbeit beginnt, wechselt der Status zu „in Arbeit“. Nur in diesem Status können Arbeitsstunden (Kommazahlen, z. B. 1,5) und Materialkosten in Euro gebucht werden; Buchungen mit Werten kleiner oder gleich 0 werden ignoriert. Ist die Reparatur beendet, wird der Auftrag abgeschlossen und erhält den Status „fertig“. Holt die Kundin das Fahrzeug ab, wechselt der Status zu „abgeholt“; das Programm meldet dabei zurück, ob die Abholung zulässig war.

Andere Statuswechsel als die beschriebenen sind nicht erlaubt und bleiben wirkungslos. Der Rechnungsbetrag ergibt sich aus den gebuchten Stunden multipliziert mit dem Stundensatz von 85,00 Euro zuzüglich der Materialkosten. Kennzeichen, Beschreibung, Status und Rechnungsbetrag müssen abgefragt werden können.

Material 3: Testprogramm des Auszubildenden
Reparaturauftrag a = new Reparaturauftrag("OS-KM 412", "Bremsen quietschen");
a.stundenBuchen(1.5);
a.beginnen();
a.stundenBuchen(2.0);
a.materialBuchen(120.0);
a.abschliessen();
a.stundenBuchen(0.5);
System.out.println(a.getStatus() + ": " + a.getRechnungsbetrag());
Der Auszubildende erwartet die Ausgabe fertig: 417.5.
  1. Erstellen Sie eine Klassenkarte der Klasse Reparaturauftrag, die alle Anforderungen erfüllt. Verwenden Sie die Methodennamen aus Material 3.
  2. Implementieren Sie die Klasse Reparaturauftrag vollständig in Java.
  3. Weisen Sie anhand Ihrer Implementierung nach, dass die Erwartung des Auszubildenden in Material 3 falsch ist, und geben Sie die tatsächliche Ausgabe an.
  4. Der Werkstattleiter schlägt vor, den Status statt als Zeichenkette als Ganzzahl (0 = angenommen, 1 = in Arbeit, 2 = fertig, 3 = abgeholt) zu speichern. Ein Mechaniker möchte stattdessen vier Wahrheitswerte angenommen, inArbeit, fertig, abgeholt. Nehmen Sie zu beiden Vorschlägen im Vergleich mit Ihrer Lösung Stellung.

Hinweise

Hinweis zu Aufgabe a)
Welche Werte muss sich ein Auftrag merken, welche lassen sich berechnen? Welche Methoden liefern etwas zurück – auch das Abholen? Was steht im Konstruktor, was wird mit Startwerten belegt?„Erstellen“ heißt: das bekannte Verfahren (Text → Klassenkarte) auf den neuen Fall übertragen – in Notation der Ergänzenden Hinweise.
Hinweis zu Aufgabe b)
Jeder Statuswechsel ist eine Methode mit einer Bedingung auf den aktuellen Status. Zeichenketten vergleichst du mit equals, nicht mit ==. Für „nur in Arbeit und positiv“ verknüpfst du zwei Bedingungen mit &&.„Implementieren“ heißt: lauffähiger Java-Quelltext – Attribute, Konstruktor und alle Methoden.
Hinweis zu Aufgabe c)
Verfolge Status, Stunden und Material Zeile für Zeile. Welche Buchungen zählt der Auszubildende offenbar mit, obwohl der Status nicht passt? Rechne seinen Wert nach, um den Denkfehler zu finden.
Hinweis zu Aufgabe d)
Mögliche Kriterien: Lesbarkeit des Quelltexts, Tippfehler-Gefahr, Anzahl möglicher ungültiger Zustände (z. B. zwei Wahrheitswerte gleichzeitig wahr), Aufwand bei einem zusätzlichen Status wie „wartet auf Teile“, Auswirkungen auf andere Klassen, wenn der Status gekapselt ist.„Stellung nehmen“ heißt: nach Abwägung eine eigene, begründete Position beziehen.

Erwartungshorizont

Erwartungshorizont zu Aufgabe a)
Reparaturauftrag
  • - kennzeichen: Zeichenkette
  • - beschreibung: Zeichenkette
  • - status: Zeichenkette
  • - stunden: Fließkommazahl
  • - material: Fließkommazahl
  • - stundensatz: Fließkommazahl
  • c Reparaturauftrag(kennzeichen: Zeichenkette, beschreibung: Zeichenkette)
  • + beginnen()
  • + stundenBuchen(h: Fließkommazahl)
  • + materialBuchen(betrag: Fließkommazahl)
  • + abschliessen()
  • + abholen(): Wahrheitswert
  • + getKennzeichen(): Zeichenkette
  • + getBeschreibung(): Zeichenkette
  • + getStatus(): Zeichenkette
  • + getRechnungsbetrag(): Fließkommazahl

Der Rechnungsbetrag wird berechnet, nicht gespeichert. Der Stundensatz kann auch als fester Wert in der Methode stehen; ein Attribut ist aber übersichtlicher. abholen() liefert laut Text eine Rückmeldung und hat daher den Rückgabetyp Wahrheitswert.

Erwartungshorizont zu Aufgabe b)
public class Reparaturauftrag {
    private String kennzeichen;
    private String beschreibung;
    private String status;
    private double stunden;
    private double material;
    private double stundensatz;

    public Reparaturauftrag(String kennzeichen, String beschreibung) {
        this.kennzeichen = kennzeichen;
        this.beschreibung = beschreibung;
        status = "angenommen";
        stunden = 0.0;
        material = 0.0;
        stundensatz = 85.0;
    }

    public void beginnen() {
        if (status.equals("angenommen")) {
            status = "in Arbeit";
        }
    }

    public void stundenBuchen(double h) {
        if (status.equals("in Arbeit") && h > 0) {
            stunden = stunden + h;
        }
    }

    public void materialBuchen(double betrag) {
        if (status.equals("in Arbeit") && betrag > 0) {
            material = material + betrag;
        }
    }

    public void abschliessen() {
        if (status.equals("in Arbeit")) {
            status = "fertig";
        }
    }

    public boolean abholen() {
        if (status.equals("fertig")) {
            status = "abgeholt";
            return true;
        }
        return false;
    }

    public String getKennzeichen() {
        return kennzeichen;
    }

    public String getBeschreibung() {
        return beschreibung;
    }

    public String getStatus() {
        return status;
    }

    public double getRechnungsbetrag() {
        return stunden * stundensatz + material;
    }
}

Wesentlich: private Attribute, Initialisierung im Konstruktor mit this, Statusprüfung mit equals in allen Übergängen, Prüfung auf positive Werte, return in allen Anfragen.

Erwartungshorizont zu Aufgabe c)

Ablauf: stundenBuchen(1.5) bei Status „angenommen“ → ignoriert. beginnen() → „in Arbeit“. 2,0 Stunden und 120,00 Euro Material werden gebucht. abschliessen() → „fertig“. stundenBuchen(0.5) bei „fertig“ → ignoriert.

Rechnungsbetrag: 2,0 · 85,00 + 120,00 = 290,00 Euro. Tatsächliche Ausgabe: fertig: 290.0.

Der Auszubildende hat mit 3,5 Stunden gerechnet (3,5 · 85,00 + 120,00 = 417,50): Er hat die Buchung vor beginnen() mitgezählt und damit übersehen, dass Buchungen nur im Status „in Arbeit“ wirken. Die Erwartung ist damit widerlegt.

Erwartungshorizont zu Aufgabe d)

Zeichenkette (eigene Lösung): gut lesbar, die Ausgabe ist direkt verständlich; aber anfällig für Tippfehler („in arbeit“), die der Compiler nicht erkennt, und Vergleiche müssen mit equals erfolgen.

Ganzzahl: Vergleiche mit == sind einfach, die Reihenfolge ist als Zahl ausdrückbar (z. B. „status < 2“). Der Quelltext wird aber schwer lesbar („Was bedeutet 2?“), und ungültige Werte wie 7 sind möglich. Durch die Kapselung (Status privat, Änderung nur über Methoden) bleibt die Umstellung auf die Klasse beschränkt; getStatus() kann weiterhin eine Zeichenkette liefern.

Vier Wahrheitswerte: ungeeignet, weil es 16 Kombinationen, aber nur 4 gültige Zustände gibt; bei jedem Wechsel müssen zwei Attribute konsistent geändert werden. Ein weiterer Status („wartet auf Teile“) erfordert ein neues Attribut und Änderungen in allen Methoden.

Mögliche Stellungnahme: Zeichenkette und Ganzzahl sind beide vertretbar, solange der Status gekapselt bleibt und nur die Methoden der Klasse ihn ändern; aus Gründen der Lesbarkeit ist die Zeichenkette vorzuziehen. Der Vorschlag mit vier Wahrheitswerten ist abzulehnen.