MINT lernen

Attribute und Konstruktoren

Zwei Textaufgaben mit Hinweisen und Erwartungshorizont zu Standardwerten, this und überladenen Konstruktoren.

Dein Fortschritt:
0 / 0 Aufgaben
1

Spielstände im Jump-’n’-Run

AFB I–II

In einem selbst programmierten Jump-’n’-Run wird für jede Person ein Spielstand gespeichert. Neue Spielerinnen und Spieler beginnen in Level 1. Wer einen Code aus einem Gewinnspiel hat, darf direkt in einem höheren Level einsteigen und bekommt dafür Münzen geschenkt. Erzeugt werden drei Spielstände:

new Spielstand("Kira"), new Spielstand("Leo", 4) und new Spielstand("Ava", 12).

Material: Spielstand.java (Ausschnitt)
public class Spielstand {
    private String spieler;
    private int level;
    private int muenzen;
    private boolean profi;

    public Spielstand(String spieler) {
        this.spieler = spieler;
        level = 1;
    }

    public Spielstand(String spieler, int level) {
        this.spieler = spieler;
        this.level = level;
        muenzen = 50 * level;
        if (level >= 10) {
            profi = true;
        }
    }
}
Weitere Methoden sind weggelassen.
  1. Ermittle die Objektkarten der drei Spielstände direkt nach dem Erzeugen.
  2. Erkläre, woher Java bei jedem new weiß, welcher der beiden Konstruktoren ausgeführt wird.
  3. Ein Mitschüler schreibt Spielstand s = new Spielstand(); und sagt: „Das geht, Java hat doch immer einen Standardkonstruktor.“ Begründe, warum javac diese Zeile nicht übersetzt.

Hinweise

Hinweis zu Aufgabe a)
Starte bei jedem Objekt mit den Standardwerten (null, 0, false) und führe dann den passenden Konstruktor Zeile für Zeile aus.
Hinweis zu Aufgabe b)
Vergleiche die Argumente in den Klammern mit den Parameterlisten der Konstruktoren: Anzahl und Typen.
Hinweis zu Aufgabe c)
Wann legt Java einen Standardkonstruktor ohne Parameter an – immer oder nur unter einer Bedingung?

Erwartungshorizont

Erwartungshorizont zu Aufgabe a)
: Spielstand
  • spieler = "Kira"
  • level = 1
  • muenzen = 0
  • profi = false
: Spielstand
  • spieler = "Leo"
  • level = 4
  • muenzen = 200
  • profi = false
: Spielstand
  • spieler = "Ava"
  • level = 12
  • muenzen = 600
  • profi = true

Bei Kira setzt der Konstruktor nur spieler und level; muenzen und profi behalten die Standardwerte 0 und false. Leo: 50 · 4 = 200 Münzen, Level 4 ist kleiner als 10. Ava: 50 · 12 = 600 Münzen, Level 12 ≥ 10, also Profi.

Erwartungshorizont zu Aufgabe b)

Die Klasse hat zwei Konstruktoren mit gleichem Namen, aber verschiedenen Parameterlisten – der Konstruktor ist überladen. Java vergleicht Anzahl und Typen der Argumente beim new mit den Parameterlisten: ("Kira") passt nur zu (String spieler), ("Leo", 4) nur zu (String spieler, int level).

Erwartungshorizont zu Aufgabe c)

Java legt einen Standardkonstruktor ohne Parameter nur dann automatisch an, wenn die Klasse keinen eigenen Konstruktor hat. Spielstand hat zwei eigene Konstruktoren, beide mit mindestens einem Parameter. Zu einem Aufruf ohne Argumente passt keiner, also meldet javac: no suitable constructor found for Spielstand(no arguments). Die Aussage des Mitschülers stimmt also nicht.

2

Die Konzertkarte ohne Band

AFB II–III

Für das Schulfest verkauft die Schülerfirma Karten für ein Konzert der Schulband „Lichtblick“. Sitzplätze haben eine Reihe und einen Preis, in den Reihen 1 bis 3 gibt es VIP-Zugang zum Backstage-Bereich. Außerdem soll es Stehplätze geben: Sie kosten immer 25,00 €, haben die Reihe 0 und nie VIP-Zugang.

Beim ersten Test verkauft Jonas eine Karte für Reihe 2 zu 39,90 € (Material 2). Seine Mitschülerin schlägt vor, die Parameter im Konstruktor einfach b, r und p zu nennen – dann brauche man kein this.

Material 1: Konzertkarte.java
public class Konzertkarte {
    private String band;
    private int reihe;
    private double preis;
    private boolean vip;

    public Konzertkarte(String band, int reihe, double preis) {
        band = band;
        this.reihe = reihe;
        preis = preis;
        if (reihe <= 3) {
            vip = true;
        }
    }

    public void ausgeben() {
        System.out.println(band + ", Reihe " + reihe + ", " + preis + " Euro, VIP: " + vip);
    }
}
Das Programm wird ohne Fehlermeldung übersetzt.
Material 2: Test in der Klasse Kasse
Konzertkarte k = new Konzertkarte("Lichtblick", 2, 39.9);
k.ausgeben();
Ausschnitt aus main
  1. Stelle eine begründete Vermutung auf, was der Test in Material 2 ausgibt.
  2. Tatsächlich erscheint null, Reihe 2, 0.0 Euro, VIP: true. Interpretiere diese Ausgabe: Welche Zeilen des Konstruktors wirken, welche nicht, und warum?
  3. Implementiere eine korrigierte Klasse mit einem zweiten Konstruktor für Stehplätze, dem nur der Bandname übergeben wird.
  4. Beurteile den Vorschlag, die Parameter b, r und p zu nennen.

Hinweise

Hinweis zu Aufgabe a)
Schau genau hin: Zwei Zuweisungen sehen anders aus als die dritte.„Vermutung aufstellen“ heißt: vorher festlegen, was du erwartest – auch wenn sie sich später als falsch herausstellt.
Hinweis zu Aufgabe b)
Im Konstruktor gibt es zweimal den Namen band: Parameter und Attribut. Welcher ist gemeint, wenn kein this davorsteht? Welche Standardwerte haben String und double?
Hinweis zu Aufgabe c)
Zwei Konstruktoren mit gleichem Namen, aber verschiedenen Parametern. Warum wäre es keine gute Idee, Stehplätze mit dem vorhandenen Konstruktor und Reihe 0 anzulegen? Probiere es gedanklich aus.
Hinweis zu Aufgabe d)
Kriterien: Löst der Vorschlag das Problem? Lesbarkeit des Konstruktorkopfs, Verständlichkeit für andere, übliche Schreibweise in Java.

Erwartungshorizont

Erwartungshorizont zu Aufgabe a)

Jede begründete Vermutung ist richtig bearbeitet, z. B.: „Lichtblick, Reihe 2, 39.9 Euro, VIP: true, weil alle Werte übergeben werden und 2 ≤ 3 ist“ – oder schon: „Bandname und Preis fehlen, weil dort this fehlt.“

Erwartungshorizont zu Aufgabe b)

In band = band; und preis = preis; meinen beide Seiten den Parameter, denn er überdeckt im Konstruktor das gleichnamige Attribut. Der Parameter bekommt seinen eigenen Wert noch einmal – die Attribute bleiben unverändert auf ihren Standardwerten: null für den String, 0.0 für den double.

this.reihe = reihe; wirkt, weil this.reihe ausdrücklich das Attribut des Objekts meint. Die if-Abfrage setzt wegen 2 ≤ 3 vip auf true. javac meldet nichts, weil die Zeilen erlaubt sind – es ist ein Denkfehler, kein Übersetzungsfehler.

Erwartungshorizont zu Aufgabe c)
public class Konzertkarte {
    private String band;
    private int reihe;
    private double preis;
    private boolean vip;

    public Konzertkarte(String band, int reihe, double preis) {
        this.band = band;
        this.reihe = reihe;
        this.preis = preis;
        if (reihe <= 3) {
            vip = true;
        }
    }

    public Konzertkarte(String band) {
        this.band = band;
        this.reihe = 0;
        this.preis = 25.0;
        this.vip = false;
    }

    public void ausgeben() {
        System.out.println(band + ", Reihe " + reihe + ", " + preis + " Euro, VIP: " + vip);
    }
}

Test: Lichtblick, Reihe 2, 39.9 Euro, VIP: true und für new Konzertkarte("Lichtblick"): Lichtblick, Reihe 0, 25.0 Euro, VIP: false.

Der eigene Konstruktor ist nötig: new Konzertkarte("Lichtblick", 0, 25.0) ergäbe VIP: true, weil 0 ≤ 3 ist. Die Zeilen reihe = 0 und vip = false dürfen fehlen (Standardwerte), machen die Absicht aber deutlich.

Erwartungshorizont zu Aufgabe d)

Dafür: Mit anderen Namen gibt es keine Überdeckung; band = b; setzt das Attribut richtig, der Fehler aus b) wäre behoben.

Dagegen: Der Konstruktorkopf Konzertkarte(String b, int r, double p) verrät nicht mehr, was übergeben werden muss – man muss den Rumpf lesen. In Java ist es üblich, Parameter wie die Attribute zu nennen und mit this zu unterscheiden; das kennen alle, die den Code später lesen.

Mögliches Urteil: Der Vorschlag behebt den Fehler, verschlechtert aber die Lesbarkeit. Besser ist, die sprechenden Namen zu behalten und this konsequent zu schreiben. Ein anderes Urteil ist vollständig, wenn es beide Seiten abwägt.