"Grundkurs Programmieren in Java - (7. Auflage, 2014)"
2001-2014, Carl Hanser Verlag

Lösungsvorschlag zu Aufgabe 8.8 (Version 3.0)

(c) 2001-2014 D. Ratz, J. Scheffler, D. Seese, J. Wiesenberger

a)

Aufbau der Klasse

b)

Es wird ein Objekt (eine Instanz) der Klasse TennisSpieler, erzeugt. Durch
  TennisSpieler maier;
wird allerdings nur eine Referenzvariable maier erzeugt, die den Wert null besitzt. Erst
  maier = new TennisSpieler();
legt das referenzierte Objekt an.

Ein Objekt der Klasse TennisSpieler

c)

Die this-Referenz ist ein automatisch generierter Verweis auf das Objekt selbst (Selbst-Referenz). In der Methode altersDifferenz kann damit zwischen der formalen Variable alter (die wie eine lokale Variable behandelt wird und somit die Instanzvariable alter verdeckt) und der Instanzvariable alter des aufrufenden Objekts unterschieden werden.

Grafische Darstellung: siehe Grafik Aufgabenteil b)

d)

Der Zugriff auf die Variablen und Methoden der Klasse erfolgt über die Punktnotation (den Punkt-Operator), z.B.
  maier.alter = 25;
um auf die Instanzvariable alter des oben erzeugten Objektes maier zuzugreifen.

e)

Ein Konstruktor dient zur Erzeugung eines Objektes (einer Instanz der Klasse) in Verbindung mit dem new-Operator. Sein Name ist identisch mit dem Namen der Klasse. Ein Konstruktor für die Klasse TennisSpieler könnte z. B. wie folgt aussehen:
  public TennisSpieler (String name, int alter) {
    this.name = name;
    this.alter = alter;
  }
Der Default-Konstruktor ohne Argumente ist nicht mehr vorhanden, wenn er nicht explizit geschrieben worden ist, da er nur automatisch ergänzt wird, wenn kein anderer Konstruktor implementiert wurde.

f)

Instanzvariablen sind an ein Objekt gebunden, so dass mit jeder Erzeugung eines neuen Objektes auch neue Instanzvariablen erzeugt werdenn. Werden deren Werte verändert, so gilt dies nur innerhalb des Objektes. Klassenvariablen (innerhalb einer Klasse mit dem Attribut static versehen) hingegen werden nur einmal (beim Laden der Klasse zur Laufzeit des Programmes) angelegt. Alle Objekte (Instanzen) der Klasse können auf sie zugreifen, so dass eine Änderung ihrer Werte innerhalb eines Objektes auch in allen anderen Objekten erfolgt.

g)

Eine solche Erweiterung der Klasse TennisSpieler wäre z.B.
  public TennisSpieler verfolger = null; // Verfolger in der Weltrangliste
  public int startNummer;                // Startnummer im  Wettbewerb

h)

Eine solche Erweiterung der Klasse TennisSpieler wäre z.B.
  public static int folgeNummer = 1; // Naechste Nummer
so dass die erste zu vergebende Startnummer die Eins wäre.

i)

Mögliche Konstruktoren für die Klasse TennisSpieler wären z.B.
  public TennisSpieler (String name, int alter) {
    this.name = name;
    this.alter = alter;
    startNummer = folgeNummer++;
  }

  public TennisSpieler (String name, int alter, TennisSpieler verfolger) {
    this.name = name;
    this.alter = alter;
    this.verfolger = verfolger;
    startNummer = folgeNummer++;
  }

j)

Nach der Anweisung
    TennisSpieler maier = new TennisSpieler("H. Maier", 68);
hat startNummer im Objekt maier den Wert 1 und folgeNummer hat den Wert 2. Nach der Anweisung
    TennisSpieler schmid = new TennisSpieler("G. Schmid", 45, maier);
hat startNummer im Objekt schmid den Wert 2 und folgeNummer sowohl für das Objekt maier als auch für das Objekt schmid den Wert 3. Nach der Anweisung
    TennisSpieler berger = new TennisSpieler("I. Berger", 36, schmid);
hat startNummer im Objekt \verb|berger| den Wert 3 und folgeNummer sowohl für das Objekt berger als auch für das Objekt schmid als auch für das Objekt maier den Wert 4.

k)

Instanzmethoden sind an ein Objekt gebunden und erst nach der Erzeugung des Objekts aufrufbar, während Klassenmethoden (mit dem Attribut static versehen) bereits vor der Erzeugung einer Instanz der Klasse aufgerufen werden können. Sie können aber nicht auf Instanzvariablen der Klasse oder auf den this-Zeiger zugreifen.

l)

Eine Realisierung der Methode istLetzter könnte wie folgt aussehen:
  public boolean istLetzter () {
    return (verfolger == null);
  }
Das Programmstück
    System.out.println(maier.istLetzter());
    System.out.println(schmid.istLetzter());
    System.out.println(berger.istLetzter());
würde somit die Werte true, false und false ausgeben.

m)

Das Programmstück würde die Zeilen
    H. Maier (1)
    G. Schmid (2) liegt vor H. Maier (1)
    I. Berger (3) liegt vor G. Schmid (2) liegt vor H. Maier (1)
ausgeben.

n)

Man muss die Variablen startNummer und folgeNummer für den Anwender der Klasse verbergen. Dies geschieht dadurch, dass man die Variablen als private deklariert. Einen lesenden Zugriff auf die Startnummern kann man mit neuen Methoden ermöglichen.
  private int startNummer;            // Startnummer
  private static int folgeNummer = 1; // Naechste Nummer
  public int getStartNummer () {
    return startNummer;
  }
  public static int getFolgeNummer () {
    return folgeNummer;
  }
Damit wären im Anwenderprogramm z.B. die nachfolgende Anweisungen möglich:
  System.out.println("Nummer H. Maier: " + maier.getStartNummer());
  System.out.println("Naechste zu vergebende Nummer: " +
                     TennisSpieler.getFolgeNummer());