Spielerei mit Javas dynamischer Bindung

Werfen wir eine Blick auf folgendes Java-Programm:

class PrahlerOber
{
 int i = 1;

 void m()
 {
  System.out.println( "Ich bin toll" );
 }
}

class PrahlerUnter extends PrahlerOber
{
 int i = 2;

 @Override void m()
 {
  super.m();
  System.out.println( "Und ich bin noch toller" );
  System.out.println( super.i );
  System.out.println( i );
 }
}

Die Methode m() aus PrahlerUnter bezieht sich mittels super.m() auf die Methode der Oberklasse. Im zweiten Fall können wir auf die verdeckte Objektvariable mit super.i zugreifen. super ist vergleichbar mit this und kann auch genauso eingesetzt werden, doch super geht in den Namensraum der Oberklasse.

Wir rufen zwar in m() die überschriebene Methode auf, benötigen aber dafür ihren Namen. Interessant wäre eine Variante von super – die es aber nicht gibt –, mit der der Methodenname egal ist. So muss bei einer Änderung des Namens der Quellcode an zwei Stellen angepasst werden. Ein super() für die Oberklasse existiert nur für Konstruktoren.

Eine Aneinanderreihung von super-Schlüsselwörtern bei einer tieferen Vererbungshierarchie ist nicht möglich. Hinter einem super muss eine Objekteigenschaft stehen. Anweisungen wie super.super.i sind somit immer ungültig. Für Variablen gibt es jedoch eine Möglichkeit, die sich durch einen Cast in die Oberklasse ergibt. Wir erfinden eine neue Unterklasse Oberangeber, die wiederum von PrahlerUnter erbt.

class Oberangeber extends PrahlerUnter
{
 @Override void m()
 {
  System.out.println( ((PrahlerOber)this).i );
 }
}

Die this-Referenz entspricht einem Objekt vom Typ Oberangeber. Wenn wir dies aber in den Typ PrahlerOber konvertieren, bekommen wir genau das i aus der Basisklasse unserer Hierarchie. Wir erkennen hier eine sehr wichtige Eigenschaft von Java, nämlich, dass Variablen nicht dynamisch gebunden werden. Anders wäre es, wenn wir die Funktion ändern in:

void m()
{
 ((PrahlerOber)this).m();
}

Hier wird nicht wie erwartet m() aus PrahlerOber aufgerufen, sondern die eigene Funktion m(), sodass wir in einer Rekursion landen. Der Grund dafür liegt in der dynamischen Bindung.