Übungsaufgaben zum Implementieren von Klassen: Konstruktor, Getter, Setter und Objekterzeugung

https://bildung.social/@oerinformatik/

https://oer-informatik.de/klassen-implementieren-uebungsaufgaben

Objektorientierte Programmierung, Klassen, Konstruktor, Getter und Setter, Kapselung, Vererbung, Pseudocode, Call by Reference, Übungsaufgaben, Prüfungsvorbereitung

tl/dr; (Bearbeitungszeit insgesamt 71 min, mehrere Aufgaben): Zwei Übungsaufgaben, in denen Du Klassen in Pseudocode implementierst: Interessen und Profile einer Freizeit-App mit Konstruktor, Gettern, Settern mit Prüfung und Fehlersuche in fremdem Code sowie gleichschließende Fahrradschlösser mit Unterklassenkonstruktoren, fortlaufenden Seriennummern, Anmeldung mit this und Übergabe von Arrays. Alle Lösungen sind ausgeblendet und mit Punkteverteilung versehen [AI-Assisted]. (Zuletzt geändert am 28.10.2026)

Diese Übungsaufgaben gehören zum Artikel Klassen implementieren: Konstruktor, Getter, Setter und Objekterzeugung. Sie setzen voraus, dass Du UML-Klassendiagramme lesen und Algorithmen in Pseudocode notieren kannst.

Im Lehrartikel entsteht aus diesem Klassendiagramm der Schulbibliothek Schritt für Schritt der Code; die Aufgaben übertragen das auf neue Klassen:

Klassendiagramm der Schulbibliothek aus dem Lehrartikel mit den Klassen Buch, Fachbuch, Leser und Ausleihe (mit KI erstellt)

Hinweise zur Bearbeitung: Von FIA wird erwartet, dass ihnen Aufgaben auf Profilkompetenz-Ebene (Aufgabe 3.1 und Aufgabe 3.2) keine Probleme bereiten. Schreibe Deine Lösung zuerst auf Papier, bevor Du die Beispiellösung aufklappst. Die Beispiellösungen verwenden einen Java-nahen Pseudocode:

  • Methodenköpfe als + name(Typ parameter): Rückgabetyp, Konstruktoren ohne Rückgabetyp.

  • Zuweisung mit =, Vergleich mit == und !=, logische Verknüpfung mit and, or, not; Zeichenketten vergleichst Du mit equals.

  • Objekte entstehen mit new Klasse(…), das aktuelle Objekt ist this, der Konstruktor der Oberklasse super(…), ein fehlendes Objekt null.

  • Listen mit add, size, get(i); Arrays mit feld[i] und feld.length; Schleifen als for, while und foreach (Typ element in sammlung).

Jede andere eindeutige Schreibweise (deutsche Schlüsselwörter, UML-Schreibweise der Parameter, echte Programmiersprache) ist ebenfalls richtig. Auf private Attribute anderer Klassen greifst Du nur über Getter und Setter zu. Andere fachlich richtige Lösungen bekommen die volle Punktzahl.

Du möchtest eigene Aufgaben zum Üben von einem KI-Sprachmodell generieren lassen?

Kopiere den Text in ein KI-Sprachmodell Deiner Wahl und passe Kompetenzstufe, Anzahl, Bearbeitungszeit und Szenario bei Bedarf an. Wie die Aufgaben aufgebaut sind, beschreibt der Artikel Wie sind die Aufgaben aufgebaut?. Prüfe die Ergebnisse mit dem Lehrartikel: KI-Sprachmodelle machen Fehler.

Erstelle neue Übungsaufgaben zum Thema „Implementieren von Klassen:
Konstruktor, Getter, Setter und Objekterzeugung“.

Bauplan: Halte Dich an Aufbau, Kompetenzstufen, Operatoren,
Anforderungsbereiche, Punkte und Zeitschätzung, die im Artikel
https://oer-informatik.de/aufgaben-aufbau beschrieben sind.

Fachliche Grundlage:
- https://oer-informatik.de/klassen-implementieren
- https://oer-informatik.de/uml-klassendiagramm
- https://oer-informatik.de/pseudocode
- Stilbeispiel: https://oer-informatik.de/klassen-implementieren-uebungsaufgaben

Die Aufgaben sollen Inhalte zu diesen Schlagwörtern abdecken:
- Objektorientierte Programmierung
- Klassen
- Konstruktor
- Getter und Setter
- Kapselung
- Vererbung
- Pseudocode
- Call by Reference

Kompetenzstufe: Profilkompetenz (alternativ: Basiskompetenz, Kernkompetenz, Expertise)
Anzahl: 1 Aufgabe mit Teilaufgaben
Bearbeitungszeit in Minuten ca.: <5 bis 30 min>
Szenario: eines der Szenarien aus dem Bauplan

Vorgehen:
1. Lies zuerst die verlinkten Artikel. Kannst Du keine Webseiten
   abrufen, sag mir das, statt zu raten.
2. Steht bei einer Angabe noch ein Platzhalter in <…>, frag mich
   zuerst danach. Richte Punkte und Zahl der Teilaufgaben nach der
   Bearbeitungszeit (ca. 0,9 min je Punkt).
3. Gib je Aufgabe Titel mit Kompetenzstufe, Ausgangssituation und
   Teilaufgaben mit Operator und Punktzahl aus, dazu die geschätzte
   Bearbeitungszeit.
4. Gib die Beispiellösungen mit Punkteverteilung erst aus, wenn ich
   danach frage.

Aufgabe 3.1: Interessen und Profile in einer Freizeit-App (Profilkompetenz)

(ca. 36 min Bearbeitungszeit)

Du bist Auszubildende*r im Entwicklungsteam der Let’s Meet GmbH in Bielefeld. Die Firma betreibt eine App, über die sich Menschen zu gemeinsamen Freizeitaktivitäten verabreden. Unter der Leitung von Yusuf Demir wird das Backend neu programmiert. Du setzt gemeinsam mit Deinem Mit-Azubi Jonas Weber die Fachklassen für die Profile um.

Jedes Konto kann Interessen angeben. Ein Interesse besteht aus der Bezeichnung eines Hobbys (z. B. „Wandern“), dessen Kategorie (z. B. „Natur“) und einer Priorität von −100 (Abneigung) bis 100 (Lieblingshobby). Yusuf Demir hat Jonas Weber dazu im Team-Chat geschrieben:

„Für die Interessen brauchen wir eine eigene Klasse Interesse. Von außen soll niemand direkt an die Daten herankommen. Angelegt wird ein Interesse immer komplett, also Hobby, Kategorie und Priorität auf einmal. Lesen dürfen andere Klassen alles. Ändern lässt sich danach nur noch die Priorität, Hobby und Kategorie stehen fest. Und ich will ein Interesse fragen können, ob es eine Abneigung ist, also ob seine Priorität unter null liegt.“

Jonas hat daraus diesen ersten Entwurf notiert:

Interesse
------------------------------------------------
+ hobby: String
- kategorie: String
- prioritaet: String
------------------------------------------------
+ Interesse(hobby: String, prioritaet: Integer): void
+ getHobby(): String
+ getKategorie(): String
+ setKategorie(kategorie: String)
+ setPrioritaet(prioritaet: Integer)
+ istAbneigung(prioritaet: Integer): Boolean

a) Vergleiche Jonas’ Entwurf mit Yusufs Nachricht. Benenne alle Abweichungen und gib danach das korrigierte UML-Klassendiagramm vollständig an. (7 Punkte)

Abweichungen (je 0,5 Punkte, zusammen 3,5 Punkte):

  1. hobby ist öffentlich; „niemand soll direkt an die Daten herankommen“ verlangt - hobby.

  2. prioritaet ist als String angelegt; für Zahlenvergleiche (unter null, Begrenzung auf −100 bis 100) braucht es Integer.

  3. Dem Konstruktor fehlt der Parameter für die Kategorie, obwohl ein Interesse immer komplett angelegt wird.

  4. Der Konstruktor hat mit void einen Rückgabetyp; Konstruktoren haben keinen.

  5. getPrioritaet(): Integer fehlt, obwohl andere Klassen alles lesen dürfen.

  6. setKategorie widerspricht Yusufs Nachricht, dass die Kategorie feststeht.

  7. istAbneigung hat einen Parameter; die Methode soll aber die eigene Priorität des Objekts prüfen und braucht deshalb keinen.

Korrigiertes Klassendiagramm (3,5 Punkte):

Klassendiagramm der Klasse Interesse mit drei privaten Attributen, Konstruktor, drei Gettern, einem Setter und der Methode istAbneigung (mit KI erstellt)

Bewertung des Diagramms: drei private Attribute mit Datentyp 1 Punkt; Konstruktor mit drei typisierten Parametern und ohne Rückgabetyp 1 Punkt; drei Getter und nur ein Setter 1 Punkt; istAbneigung(): Boolean ohne Parameter 0,5 Punkte.

Ebenfalls richtig: kategorie als Aufzählung (Kategorie <<enumeration>>), Getter für Wahrheitswerte in der Form isAbneigung().

b) Implementiere die Methoden getPrioritaet und setPrioritaet in Pseudocode. Der Setter soll Werte über 100 durch 100 und Werte unter −100 durch −100 ersetzen. (5 Punkte)

+ getPrioritaet(): Integer {
    return prioritaet
}

+ setPrioritaet(Integer prioritaet) {
    if (prioritaet > 100) {
        this.prioritaet = 100
    } else if (prioritaet < -100) {
        this.prioritaet = -100
    } else {
        this.prioritaet = prioritaet
    }
}

Bewertung: Getter-Kopf ohne Parameter mit Rückgabetyp 0,5 Punkte, Rückgabe des Attributs 1 Punkt; Setter-Kopf mit typisiertem Parameter und ohne Rückgabetyp 1 Punkt; je Grenze 1 Punkt (2); Zuweisung an das Attribut (mit this, wenn Parameter und Attribut gleich heißen) 0,5 Punkte. Fehlt this bei gleichem Namen, wird das Attribut nie gesetzt: 0,5 Punkte Abzug.

c) Implementiere den Konstruktor der Klasse Interesse. Die Begrenzung der Priorität aus b) soll dabei nicht noch einmal programmiert werden. (3 Punkte)

+ Interesse(String hobby, String kategorie, Integer prioritaet) {
    this.hobby = hobby
    this.kategorie = kategorie
    setPrioritaet(prioritaet)
}

Bewertung: Kopf mit Klassennamen, drei typisierten Parametern und ohne Rückgabetyp 1 Punkt; Zuweisung von hobby und kategorie mit this 1 Punkt; Aufruf des Setters statt direkter Zuweisung 1 Punkt. So kann auch ein neu erzeugtes Interesse keine ungültige Priorität bekommen (new Interesse("Klettern", "Sport", 130) speichert 100).

d) Implementiere die Methode istAbneigung. (2 Punkte)

+ istAbneigung(): Boolean {
    return prioritaet < 0
}

Bewertung: Kopf mit Rückgabetyp Boolean 1 Punkt; Rückgabe des Vergleichs 1 Punkt. Eine Lösung mit if (prioritaet < 0) { return true } else { return false } ist ebenso richtig.

e) Jonas Weber hat mit der Klasse Benutzer begonnen und eine kleine Testklasse geschrieben. Der Konstruktor soll Konto-ID, Vorname und Geburtsdatum übernehmen, getVorname den Vornamen liefern und setProfilSichtbar die Sichtbarkeit des Profils („alle“ oder „kontakte“) ändern. Für Datumswerte gibt es die Klasse Datum mit dem Konstruktor Datum(jahr: Integer, monat: Integer, tag: Integer) und den statischen Methoden Datum.heute(): Datum und Datum.jahreZwischen(von: Datum, bis: Datum): Integer (Anzahl der vollendeten Jahre).

01  class Benutzer {
02      - Integer benutzerId
03      - String vorname
04      - Datum geburtsdatum
05      - String profilSichtbar = "kontakte"
06      - List<Interesse> interessen = new List<Interesse>()
07
08      + void Benutzer(Integer benutzerId, String vorname, Datum geburtsdatum) {
09          this.benutzerId = benutzerId
10          this.vorname = vorname
11          geburtsdatum = geburtsdatum
12      }
13
14      + getVorname(String vorname): String {
15          return vorname
16      }
17
18      + getAlter(): Integer {
19          return Datum.jahreZwischen(geburtsdatum, Datum.heute())
20      }
21
22      + setProfilSichtbar(String wert): String {
23          profilSichtbar = wert
24      }
25  }

    // Testklasse
30  Benutzer noah = Benutzer(13, "Noah", new Datum(2009, 3, 12))
31  noah.profilSichtbar = "alle"
32  Ausgabe(noah.getVorname())

ea) Analysiere den Code. Nenne sechs Fehler mit Zeilennummer, begründe sie kurz und gib jeweils die korrigierte Zeile an. (6 Punkte)

Fehler in der Klasse Benutzer und in der Testklasse
Zeile Fehler Korrektur
08 Ein Konstruktor hat keinen Rückgabetyp, auch nicht void. Mit void ist es eine gewöhnliche Methode, und new Benutzer(…) findet keinen passenden Konstruktor. + Benutzer(Integer benutzerId, String vorname, Datum geburtsdatum) {
11 this fehlt: Der Parameter verdeckt das Attribut und wird sich selbst zugewiesen; das Attribut geburtsdatum bleibt leer (null), getAlter() scheitert. this.geburtsdatum = geburtsdatum
14/15 Ein Getter hat keinen Parameter. So liefert er den übergebenen Parameter statt des Attributs, und der Aufruf in Zeile 32 passt nicht. + getVorname(): String { und return vorname (bzw. this.vorname)
22 Ein Setter gibt nichts zurück; der Kopf verspricht einen String, im Rumpf fehlt aber return. + setProfilSichtbar(String wert) { (oder Rückgabe Boolean, siehe eb)
30 Das Objekt wird ohne new erzeugt. Benutzer noah = new Benutzer(13, "Noah", new Datum(2009, 3, 12))
31 Direkter Zugriff auf das private Attribut profilSichtbar von außerhalb der Klasse. noah.setProfilSichtbar("alle")

Bewertung: je Fehler mit Zeile, Begründung und Korrektur 1 Punkt. Als weiterer Fehler zählt auch der Hinweis, dass setProfilSichtbar beliebige Texte und für Minderjährige die Sichtbarkeit „alle“ zulässt (siehe eb).

eb) Nach den Vorgaben der Datenschutzbeauftragten Dr. Marta Kowalczyk ist das Profil von Minderjährigen immer nur für Kontakte sichtbar. Implementiere setProfilSichtbar neu: Es sind nur die Werte „alle“ und „kontakte“ zulässig; für Personen unter 18 Jahren darf nur „kontakte“ gesetzt werden. Die Methode liefert true, wenn der Wert übernommen wurde, sonst false und lässt die Sichtbarkeit unverändert. (4 Punkte)

+ setProfilSichtbar(String wert): Boolean {
    if (not wert.equals("alle") and not wert.equals("kontakte")) {
        return false
    }
    if (wert.equals("alle") and getAlter() < 18) {
        return false
    }
    profilSichtbar = wert
    return true
}

Bewertung: Kopf mit Parameter und Rückgabetyp Boolean 1 Punkt; Prüfung der zulässigen Werte 1 Punkt; Altersprüfung über getAlter() (nicht über ein eigenes Attribut alter) 1 Punkt; Zuweisung und beide Rückgaben 1 Punkt.

Für Sabine Hoffmann (geboren 14.05.1963) liefert setProfilSichtbar("alle") true, setProfilSichtbar("niemand") dagegen false; die Sichtbarkeit bleibt „alle“.

f) Implementiere in der Klasse Benutzer die Methode

+ interesseHinzufuegen(String hobby, String kategorie, Integer prioritaet)

Gibt es in der Liste interessen schon ein Interesse mit derselben Hobbybezeichnung, wird nur dessen Priorität geändert. Sonst wird ein neues Interesse-Objekt erzeugt und der Liste hinzugefügt. (6 Punkte)

+ interesseHinzufuegen(String hobby, String kategorie, Integer prioritaet) {
    foreach (Interesse i in interessen) {
        if (i.getHobby().equals(hobby)) {
            i.setPrioritaet(prioritaet)
            return
        }
    }
    Interesse neu = new Interesse(hobby, kategorie, prioritaet)
    interessen.add(neu)
}

Der Ablauf als Aktivitätsdiagramm:

Aktivitätsdiagramm von interesseHinzufuegen: Schleife über die Interessen; bei gleicher Hobbybezeichnung wird die Priorität gesetzt und die Methode beendet, sonst wird nach der Schleife ein neues Interesse erzeugt und hinzugefügt (mit KI erstellt)

Bewertung: Kopf 1 Punkt; Schleife über die Liste 1 Punkt; Vergleich über den Getter mit equals 1 Punkt; Änderung über setPrioritaet und Beenden der Methode (oder eine Merkvariable gefunden) 1 Punkt; Objekterzeugung mit new und den Parametern in der Reihenfolge des Konstruktors 1 Punkt; Hinzufügen zur Liste 1 Punkt.

Nicht richtig: i.hobby == hobby (privates Attribut einer anderen Klasse und Vergleich der Referenzen statt der Inhalte) und i.prioritaet = prioritaet (umgeht die Begrenzung).

g) Erläutere zwei Gründe, warum die Attribute der Klasse Interesse privat sind und es für die Hobbybezeichnung keinen Setter gibt. (3 Punkte)

  • Kapselung und Gültigkeit: Weil die Attribute privat sind, kann die Priorität nur über den Setter oder den Konstruktor geändert werden. Die Begrenzung auf −100 bis 100 lässt sich deshalb nicht umgehen; ungültige Objekte können nicht entstehen. Außerdem kann die interne Darstellung später geändert werden, ohne dass andere Klassen angepasst werden müssen.

  • Unveränderliche Identität: Die Hobbybezeichnung bestimmt, um welches Interesse es sich handelt (interesseHinzufuegen sucht danach). Könnte man sie ändern, würde aus „Wandern 90“ unbemerkt „Klettern 90“, und es könnten zwei Interessen mit derselben Bezeichnung entstehen. Ein neues Hobby wird deshalb als neues Objekt angelegt; die Bezeichnung wird nur im Konstruktor gesetzt und ist danach nur lesbar.

Bewertung: erster Grund 1,5 Punkte, zweiter Grund 1,5 Punkte. Andere schlüssige Gründe (z. B. Bezug zur Datenbank, in der hobby_id Teil des Primärschlüssels ist) sind ebenfalls richtig.

h) Noah Bergmann (Konto-ID 13, geboren am 12.03.2009) hat sich registriert.

ha) Gib in Pseudocode an, wie in der Testklasse ein Benutzer-Objekt für Noah erzeugt wird und er die Interessen „Brettspiele“ (Kategorie „Spiele“, Priorität 85) und „Programmieren“ (Kategorie „Kreativ“, Priorität 90) erhält. (2 Punkte)

Benutzer noah = new Benutzer(13, "Noah", new Datum(2009, 3, 12))
noah.interesseHinzufuegen("Brettspiele", "Spiele", 85)
noah.interesseHinzufuegen("Programmieren", "Kreativ", 90)

Bewertung: Objekterzeugung mit new, Datum-Objekt und richtiger Reihenfolge der Argumente 1 Punkt; beide Aufrufe 1 Punkt. Wer die Interesse-Objekte selbst erzeugt, braucht dafür eine öffentliche Methode zum Hinzufügen; ein direkter Zugriff auf noah.interessen ist falsch.

hb) Danach werden im Herbst 2026 noch folgende Anweisungen ausgeführt:

noah.interesseHinzufuegen("Brettspiele", "Spiele", 120)
Boolean ok = noah.setProfilSichtbar("alle")

Gib an, wie viele Interesse-Objekte Noahs Liste danach enthält, welche Prioritäten sie haben und welche Werte ok und die Profilsichtbarkeit haben. Begründe kurz. (2 Punkte)

  • Die Liste enthält weiterhin zwei Objekte: „Brettspiele“ ist schon vorhanden, deshalb wird nur die Priorität geändert. Der Setter begrenzt 120 auf 100; „Programmieren“ bleibt bei 90.

  • Noah ist 17 Jahre alt. setProfilSichtbar("alle") lehnt den Wert ab: ok ist false, die Sichtbarkeit bleibt „kontakte“ (Startwert).

Bewertung: Interessen (Anzahl und beide Prioritäten) 1 Punkt; ok und Sichtbarkeit 1 Punkt.

Aufgabe 3.2: Gleichschließende Schlösser im Fahrrad-Onlineshop (Profilkompetenz)

(ca. 35 min Bearbeitungszeit)

Du bist Auszubildende*r im Entwicklungsteam von Cem Sarıkaya bei der CSB-Rad GmbH in Bielefeld. Der Onlineshop verkauft gleichschließende Fahrradschlösser der Lipper SchließTec KG: Alle Schlösser einer Schließanlage lassen sich mit demselben Schlüssel öffnen. Kundinnen und Kunden können auch einzelne Schlösser ohne Schließanlage kaufen. Jedes Schloss erhält bei CSB-Rad eine fortlaufende Seriennummer im Format LS-26- mit fünfstelliger laufender Nummer, z. B. LS-26-00417. Die Nummer 417 ist zuletzt vergeben worden.

Für das Shop-Backend hat Cem Sarıkaya folgendes Klassendiagramm entworfen:

Klassendiagramm mit den Klassen Schliessanlage, Schloss (abstrakt), Buegelschloss und Rahmenschloss (mit KI erstellt)

Zusätzlich gibt es die statische Hilfsmethode Text.fuehrendeNullen(zahl: Integer, stellen: Integer): String, die eine Zahl mit führenden Nullen auf die angegebene Stellenzahl auffüllt (Text.fuehrendeNullen(418, 5) liefert "00418"). Die Preise: Bügelschloss mit einer Bügellänge bis einschließlich 230 mm 59,90 €, mit längerem Bügel 69,90 €; Rahmenschloss 44,90 €.

a) Entwirf den Konstruktor der Klasse Schliessanlage in Pseudocode. Er übernimmt den Code und die Anzahl der Schlüssel; Werte unter 2 werden durch 2 ersetzt, weil jede Schließanlage mindestens zwei Schlüssel hat. Die Liste der Schlösser ist zu Beginn leer. (3 Punkte)

+ Schliessanlage(String code, Integer anzahlSchluessel) {
    this.code = code
    if (anzahlSchluessel < 2) {
        this.anzahlSchluessel = 2
    } else {
        this.anzahlSchluessel = anzahlSchluessel
    }
    schloesser = new List<Schloss>()
}

Bewertung: Kopf ohne Rückgabetyp 1 Punkt; Code und Schlüsselanzahl mit Mindestwert 1 Punkt; leere Liste mit new anlegen 1 Punkt. Ohne eigene Liste würde hinzufuegen später auf null zugreifen.

b) Implementiere den Konstruktor der abstrakten Klasse Schloss. Er speichert die übergebene Schließanlage, vergibt die nächste Seriennummer aus dem Klassenattribut naechsteNummer und erhöht dieses danach. Wurde eine Schließanlage übergeben, meldet sich das neue Schloss mit hinzufuegen bei ihr an. (5 Punkte)

+ Schloss(Schliessanlage anlage) {
    this.anlage = anlage
    seriennummer = "LS-26-" + Text.fuehrendeNullen(naechsteNummer, 5)
    naechsteNummer = naechsteNummer + 1
    if (anlage != null) {
        anlage.hinzufuegen(this)
    }
}

Bewertung: Kopf 0,5 Punkte; Anlage speichern (mit this) 0,5 Punkte; Seriennummer zusammensetzen 1 Punkt; Klassenattribut erhöhen 1 Punkt; Prüfung auf null 1 Punkt; Anmeldung mit this als Argument 1 Punkt.

Die Anmeldung steht am Ende, damit die Schließanlage ein vollständig initialisiertes Schloss erhält (sonst wäre die Seriennummer bei der Anmeldung noch leer).

c) Implementiere den Konstruktor der Klasse Buegelschloss. (3 Punkte)

+ Buegelschloss(Schliessanlage anlage, Integer buegellaengeMm) {
    super(anlage)
    this.buegellaengeMm = buegellaengeMm
}

Der Ablauf beim Erzeugen eines Bügelschlosses:

Sequenzdiagramm: new Buegelschloss(anlage, buegellaengeMm) ruft zuerst super(anlage) auf; der Konstruktor von Schloss setzt Anlage und Seriennummer und meldet das Schloss mit hinzufuegen(this) an; danach setzt Buegelschloss die Bügellänge (mit KI erstellt)

Bewertung: Kopf mit beiden Parametern 1 Punkt; Aufruf des Oberklassenkonstruktors mit super(anlage) als erste Anweisung 1,5 Punkte; Bügellänge setzen 0,5 Punkte. Wer Seriennummer und Anmeldung im Konstruktor von Buegelschloss wiederholt, vergibt zwei Nummern oder meldet das Schloss doppelt an.

d) Ergänze die Klassen um die fehlenden Methoden.

da) Implementiere die Methode getArt der Klasse Rahmenschloss. (1 Punkt)

db) Implementiere die Methode getPreis der Klasse Buegelschloss. (2 Punkte)

dc) Bastian Ludwig wünscht sich für die Werkstatt auf Etiketten den Text „Rahmenschloss LS-26-00431“. Eine Kollegin ergänzt in der Klasse Rahmenschloss die Methode + getEtikett(): String { return getArt() + " " + seriennummer }. Erläutere, warum sie dort direkt auf seriennummer zugreifen darf, eine Methode der Klasse Schliessanlage aber getSeriennummer() verwenden muss. (2 Punkte)

da)

+ getArt(): String {
    return "Rahmenschloss"
}

Bewertung: Kopf mit Rückgabetyp und Rückgabe der Zeichenkette 1 Punkt.

db)

+ getPreis(): Real {
    if (buegellaengeMm <= 230) {
        return 59.90
    }
    return 69.90
}

Bewertung: Kopf 0,5 Punkte; Bedingung mit richtiger Grenze (einschließlich 230 mm) 1 Punkt; beide Rückgaben 0,5 Punkte.

  1. seriennummer ist in Schloss geschützt (#, protected). Geschützte Attribute sind in der eigenen Klasse und in allen Unterklassen sichtbar; Rahmenschloss erbt von Schloss und darf deshalb direkt darauf zugreifen. Schliessanlage ist keine Unterklasse von Schloss; für sie ist das Attribut nicht sichtbar, sie muss den öffentlichen Getter verwenden (Kapselung).

Bewertung: Begriff „geschützt/protected“ mit Sichtbarkeit in Unterklassen 1 Punkt; Begründung für Schliessanlage 1 Punkt. (Hinweis: In Java ist protected zusätzlich im selben Paket sichtbar; das ist hier nicht gefragt.)

e) Zum Test baust Du einen echten Auftrag nach: Michael Hartmann vom Zweckverband Radwege OWL hat für die Schließanlage „VS-3T8B6L1“ mit 12 Schlüsseln zwölf Rahmenschlösser für die Dienstfahrräder bestellt, dazu ein Bügelschloss mit 230 mm Bügellänge für den Fahrradständer am Verwaltungsgebäude.

ea) Implementiere in Pseudocode, wie die Schließanlage, die zwölf Rahmenschlösser und das Bügelschloss erzeugt werden. Das Bügelschloss soll anschließend in einer Variablen s vom Typ Schloss gespeichert sein. (4 Punkte)

Schliessanlage anlage = new Schliessanlage("VS-3T8B6L1", 12)
for (Integer i = 1; i <= 12; i++) {
    new Rahmenschloss(anlage)
}
Schloss s = new Buegelschloss(anlage, 230)

Bewertung: Schließanlage erzeugen 1 Punkt; Schleife über zwölf Durchläufe 1 Punkt; Rahmenschlösser mit der Anlage als Argument 1 Punkt; Bügelschloss mit new in einer Variablen vom Typ der abstrakten Oberklasse 1 Punkt.

Ebenfalls richtig: Rahmenschloss r = new Rahmenschloss(anlage) in der Schleife. Nicht nötig (und falsch): zusätzlich anlage.hinzufuegen(…) aufzurufen. Das erledigt schon der Konstruktor, sonst stünde jedes Schloss doppelt in der Liste. new Schloss(anlage) ist nicht möglich, weil Schloss abstrakt ist.

eb) Gib an, welchen Wert anlage.getAnzahlSchloesser() danach liefert und welche Seriennummer das Bügelschloss s hat, wenn vorher keine weiteren Schlösser angelegt wurden. Erläutere, warum die Rahmenschlösser nicht verloren gehen, obwohl sie keiner Variablen zugewiesen werden. (3 Punkte)

  • anlage.getAnzahlSchloesser() liefert 13 (zwölf Rahmenschlösser und ein Bügelschloss).

  • Die Rahmenschlösser erhalten die Nummern 418 bis 429, das Bügelschloss als dreizehntes Schloss die Nummer 430: LS-26-00430.

  • Jedes Schloss meldet sich im Konstruktor mit anlage.hinzufuegen(this) an. Die Liste schloesser der Schließanlage speichert damit eine Referenz auf jedes Schloss. Ein Objekt bleibt erhalten, solange noch eine Referenz darauf zeigt; es ist nur nicht über eine eigene Variable, sondern über die Schließanlage erreichbar.

Bewertung: je Spiegelstrich 1 Punkt.

f) Für den Lieferschein legt ein Dienst ein Array mit so vielen Plätzen an, wie auf ein Blatt passen, und ruft damit die Methode seriennummernEintragen(ziel: String[]): Integer auf. Sie trägt die Seriennummern der Schlösser der Anlage der Reihe nach in das übergebene Array ein, höchstens so viele, wie das Array Plätze hat, und liefert die Anzahl der eingetragenen Nummern. Ist sie kleiner als die Zahl der Schlösser, druckt der Dienst ein weiteres Blatt.

fa) Implementiere die Methode seriennummernEintragen in Pseudocode. (3 Punkte)

+ seriennummernEintragen(String[] ziel): Integer {
    Integer i = 0
    while (i < ziel.length and i < schloesser.size()) {
        ziel[i] = schloesser.get(i).getSeriennummer()
        i = i + 1
    }
    return i
}

Bewertung: Kopf mit Rückgabetyp Integer 0,5 Punkte; Schleife mit beiden Grenzen (Arraylänge und Listengröße) 1 Punkt; Eintragen über den Getter 1 Punkt; Rückgabe der Anzahl 0,5 Punkte.

fb) Nach den Anweisungen aus e) wird folgender Code ausgeführt. Die Methode erhoehe ist als + erhoehe(Integer n) { n = n + 1 } implementiert.

String[] liste = new String[3]
Integer eingetragen = anlage.seriennummernEintragen(liste)
String[] kopie = liste
kopie[0] = "storniert"
kopie = new String[2]
kopie[1] = "Ersatz"
Integer anzahl = anlage.getAnzahlSchloesser()
erhoehe(anzahl)

Analysiere den Code und gib die Werte von eingetragen, liste[0], liste[2], kopie[0] und anzahl am Ende an. Begründe jeweils kurz. (5 Punkte)

  • eingetragen ist 3: Das Array hat nur drei Plätze, die Anlage aber 13 Schlösser.

  • liste[0] ist „storniert“: Die Methode hat in dasselbe Array geschrieben, das der Aufrufer über liste erreicht, weil beim Aufruf die Referenz auf das Array übergeben wird. Auch kopie = liste kopiert nur die Referenz; die Änderung über kopie ist deshalb über liste sichtbar.

  • liste[2] ist „LS-26-00420“: Die ersten drei Schlösser der Anlage haben die Nummern 418, 419 und 420.

  • kopie[0] ist null: kopie = new String[2] lässt kopie auf ein neues, leeres Array zeigen; liste und ihr Array bleiben davon unberührt, "Ersatz" landet nur im neuen Array.

  • anzahl ist weiterhin 13: Ganze Zahlen werden als Wert übergeben (call by value). erhoehe ändert nur seine lokale Kopie n.

Schema am Ende des Codes: liste zeigt auf das Array mit storniert, LS-26-00419 und LS-26-00420; kopie zeigte bis zur Neuzuweisung auf dasselbe Array und zeigt jetzt auf ein neues Array mit null und Ersatz; anzahl bleibt 13, nur die Kopie n wird 14 (mit KI erstellt)

Bewertung: je Wert mit Begründung 1 Punkt.

g) Implementiere die Methode nachbestellen(art: String): Schloss der Klasse Schliessanlage. Sie erzeugt ein neues Schloss der angegebenen Art („Bügelschloss“ mit der Standardlänge 230 mm oder „Rahmenschloss“) für diese Schließanlage und gibt es zurück. Bei einer unbekannten Art wird kein Schloss erzeugt und null zurückgegeben. (4 Punkte)

+ nachbestellen(String art): Schloss {
    if (art.equals("Bügelschloss")) {
        return new Buegelschloss(this, 230)
    }
    if (art.equals("Rahmenschloss")) {
        return new Rahmenschloss(this)
    }
    return null
}

Bewertung: Kopf mit Rückgabetyp Schloss 0,5 Punkte; Unterscheidung der Art mit equals 1 Punkt; Bügelschloss mit this als Schließanlage 1 Punkt; Rahmenschloss mit this 1 Punkt; Rückgabe null 0,5 Punkte.

Weil sich das neue Schloss im Konstruktor selbst anmeldet, ist kein zusätzliches hinzufuegen nötig. Nach den Anweisungen aus e) liefert anlage.nachbestellen("Rahmenschloss") ein Schloss mit der Nummer LS-26-00431, die Anlage hat dann 14 Schlösser; anlage.nachbestellen("Kettenschloss") liefert null.

h) Ab 2027 sollen auch Kettenschlösser verkauft werden. Ein Kettenschloss hat eine Kettenlänge in Zentimetern, die bei der Erzeugung angegeben wird und später (z. B. nach einer Kürzung in der Werkstatt) geändert werden kann. Erstelle das UML-Klassendiagramm der Klasse Kettenschloss mit Konstruktor, Get- und Set-Methode für die Kettenlänge und allen weiteren nötigen Methoden einschließlich der Beziehung zur Klasse Schloss. (3 Punkte)

Klassendiagramm: Kettenschloss erbt von der abstrakten Klasse Schloss und hat das Attribut kettenlaengeCm, einen Konstruktor, Getter, Setter sowie getArt und getPreis (mit KI erstellt)

Bewertung: Generalisierung mit hohlem Dreieck an Schloss 1 Punkt; privates Attribut mit Datentyp und Konstruktor mit beiden Parametern 1 Punkt; Getter, Setter und die beiden geerbten abstrakten Methoden getArt und getPreis (müssen implementiert werden, sonst wäre Kettenschloss ebenfalls abstrakt) 1 Punkt.


Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Übungsaufgaben zum Implementieren von Klassen: Konstruktor, Getter, Setter und Objekterzeugung” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/klassen-implementieren-uebungsaufgaben veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/programmierung/programmiergrundlagen. Erstellt mit KI-Assistenz; von mir umfassend redaktionell überarbeitet, geprüft und freigegeben. Stand: 28.10.2026.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: