Inhaltsverzeichnis

Type Casting und der Operator instanceof


Da Variablen vom Datentyp einer Oberklasse auch auf Objekte der Unterklasse zeigen können, ergeben sich Situationen, in denen erst zur Laufzeit bekannt ist, welchen Datentyp das Objekt hat, auf das eine bestimmte Variable zeigt. Wie man damit umgeht, zeige ich konkret an einem Beispiel:

Die Klasse Tier

Wir beginnen mit einer einfachen Klasse, die ein Tier beschreibt. Jedes Tier hat ein Attribut Name, dessen Wert an den Konstruktor übergeben wird. Die Methode schreibeName() schreibt ihn auf den Bildschirm:


Die Klassen Hund und Katze

Nun gibt es Tiere, die nicht nur einen Namen besitzen, sondern auch noch Methoden haben, die andere Tiere nicht haben, bspw. Hunde, die bellen können und Katzen, die miauen können. Wir modellieren sie als Unterklassen der Klasse Tier, instanzieren ein Hund-Objekt und ein Katzen-Objekt und rufen deren Methoden auf:

1.Aspekt: Zuweisung des Objekts einer Unterklasse

Einer Variable vom Datentyp Tier (Oberklasse) kann man nicht nur Objekte vom Datentyp Tier zuweisen, sondern auch Objekte beliebiger Unterklassen der Klasse Tier. Im Beipsiel unten:

Hund h = new Hund("Bello");
Tier t = h;

Nach Ausführung der Zeile 2 zeigen sowohl h als auch t auf dasselbe Hund-Objekt im Speicher.
Der Compiler geht davon aus, dass t auf Objekte vom Datentyp Tier zeigt und gestattet es, mit der Variablen t auf Attribute der Klasse Tier zuzugreifen und Methoden der Klasse Tier aufzurufen. Das geht auch dann gut, wenn t nicht auf ein Tier-Objekt sondern - wie in diesem Fall - auf ein Hund-Objekt zeigt, denn die Klasse Hund besitzt als Unterklasse der Klasse Tier ja alle ihrer Attribute und Methoden. Zulässig ist also beispielsweise t.schreibeName().
Nicht zulässig ist t.belle() in Zeile 6, obwohl t zum Zeitpunkt des Aufrufs auf ein Hund-Objekt zeigt!

Auch die Zuweisung t = k; ist zulässig, denn auch das Objekt k (vom Typ Katze) ist von einer Unterklasse der Klasse Tier. Nicht möglich ist wiederum t.miaue() in Zeile 10, obwohl t zum Zeitpunkt des Aufrufs auf ein Katze-Objekt zeigt.

Aufgaben:
  1. Entferne das Kommentarzeichen // am Beginn der Zeile 6 bzw. 10. Welche Fehlermeldung zeigt der Compiler an? Warum tut er das?
  2. Nach Zeile 10 wird folgendes Programm ergänzt:
   Katze k1 = h;
   h.schreibeName();

sind diese Anweisungen zulässig? Falls „nein“: Warum nicht? Probiere sie aus, indem Du sie ins Beispiel oben einfügst!

Lösungen

2. Aspekt: Casten

Wurmt es Dich nicht auch, dass im Falle von

Hund h = new Hund("Bello");
Tier t = h;
t.belle();

die Anweisung in Zeile 3 nicht möglich ist, obwohl wir sicher wissen, dass t gerade auf ein Hund-Objekt zeigt? Warum „weiß“ das der Compiler nicht?
Denke Dir folgende Variante:

Hund h = new Hund("Bello");
Katze k = new Katze("Snoopy");
Tier t;
if(Math.random() < 0.5){
  t = h;
} else {
  t = k;
}
t.belle();

Zur Compilezeit (also während der Compiler das Programm übersetzt und auf Korrektheit überprüft) kann der Compiler nicht wissen, ob sich bei der Ausführung des Programms in t ein Hund-Objekt oder ein Katze-Objekt befindet. Er kann nur sicher davon ausgehen, dass es ein Objekt ist, dass die Attribute und Methoden der Klasse Tier besitzt.
Falls wir als Programmierer uns sicher sind, dass in der Variable t ein Hund-Objekt ist, können wir das dem Compiler aber „sagen“, indem wir der Variable in Klammern die Klasse des Objekts voranstellen, auf das die Variable zeigt. Diesen Vorgang nennt man casten:

Aufgaben

3. Nimm in Zeile 8 das Casting weg, schreibe also Hund h2 = t;. Was passiert? Warum?

4. Wenn wir ungerechtfertigt casten, vertraut uns der Compiler dann? Probiere es aus, indem Du die Zeile 5 ersetzt durch ((Katze)t).miaue();. Was passiert? Warum?

5. Verändert das Casten durch den Term (Katze)t das Objekt, auf das t zeigt von einem Tier-Objekt zu einem Katze-Objekt? Begründe Deine Antwort!


Lösungen

3. Aspekt: instanceof

Oft kann eine Variable an einer Stelle des Programms zu verschiedenen Zeiten verschiedene Objekte enthalten, so dass wir im Programm flexibel darauf reagieren müssen. Für diesen Zweck gibt es den Operator instanceof. Damit lässt sich testen, ob ein Objekt einer bestimmten Klasse angehört.