Inselraus: Vererbung und Überschattung von statischen Variablen in Schnittstellen
Die Konstanten einer Schnittstelle können einer anderen Schnittstelle vererbt werden. Dabei gibt es einige kleine Einschränkungen. Wir wollen an einem Beispiel sehen, wie sich die Vererbung auswirkt, wenn gleiche Bezeichner in den Unterschnittstellen erneut verwendet werden. Die Basis unseres Beispiels ist die Schnittstelle BaseColors mit ein paar Deklarationen von Farben. Zwei Unterschnittstellen erweitern BaseColors, und zwar CarColors und PlaneColors, die für Farbdeklarationen für Autos und Flugzeuge stehen. Eine besondere Schnittstelle FlyingCarColors erweitert die beiden Schnittstellen CarColors und PlaneColors, denn es gibt auch fliegende Autos, die eine Farbe haben können.
interface BaseColors {
int WHITE = 0;
int BLACK = 1;
int GREY = 2;
}
interface CarColors extends BaseColors {
int WHITE = 1;
int BLACK = 0;
}
interface PlaneColors extends BaseColors {
int WHITE = 0;
int GREY = 2;
}
interface FlyingCarColors extends CarColors, PlaneColors { }
public class Colors {
public static void main( String[] args ) {
System.out.println( BaseColors.GREY ); // 2
System.out.println( CarColors.GREY ); // 2
System.out.println( BaseColors.BLACK ); // 1
System.out.println( CarColors.BLACK ); // 0
System.out.println( PlaneColors.BLACK ); // 1
System.out.println( FlyingCarColors.WHITE );
// field FlyingCarColors.WHITE is ambiguous
System.out.println( FlyingCarColors.GREY );
// field FlyingCarColors.GREY is ambiguous
}
}
Die erste wichtige Tatsache ist, dass unsere drei Schnittstellen ohne Fehler übersetzt werden können, aber nicht die Klasse Colors. Das Programm und der Compiler zeigen folgendes Verhalten:
- Schnittstellen vererben ihre Eigenschaften an die Unterschnittstellen.
CarColorsund auchPlaneColorserben die Farben WHITE, BLACK und GREY ausBaseColors. - Konstanten dürfen überdeckt werden.
CarColorsvertauscht die Farbdeklarationen von WHITE und BLACK und gibt ihnen neue Werte. Wird jetzt der Wert BLACK verlangt, liefert die Umgebung den Wert 0, währendBaseColors.BLACK 1 ergibt. AuchPlaneColorsüberdeckt die Konstanten WHITE und GREY, obwohl die Farben mit dem gleichen Wert belegt sind. - Erbt eine Schnittstelle von mehreren Oberschnittstellen, so ist es zulässig, dass die Oberschnittstellen jeweils eine gleichlautende Objektvariable haben. So erbt etwa
FlyingCarColorsvonCarColorsundPlaneColorsdie Einträge WHITE, BLACK und GREY. - Unterschnittstellen können aus zwei Oberschnittstellen die Objektvariablen gleichen Namens übernehmen, auch wenn die Konstanten einen unterschiedlichen Wert haben. Das testet der Compiler nicht.
FlyingCarColorsbekommt ausCarColorsein WHITE mit 1, aber ausPlaneColorsdas WHITE mit 0. Daher ist in dem BeispielColorsauch der Zugriff WHITE nicht möglich und führt zu einem Compilerfehler. Bei der Benutzung muss ein unmissverständlich qualifizierter Name verwendet werden, der deutlich macht, welche Objektvariable gemeint ist, also zum BeispielCarColors.WHITE oderPlaneColors.WHITE. Ähnliches gilt für die Farbe GREY. Obwohl Grau durch die ursprüngliche Deklaration beiBaseColorsund auch bei der Überschattung inPlaneColorsimmer 2 ist, ist die Nutzung durchFlyingCarColors.GREY nicht zulässig. Das ist ein guter Schutz gegen Fehler, denn wenn der Compiler dies durchließe, könnte sich im Nachhinein die Belegung von GREY inBaseColorsoderPlaneColorsohne Neuübersetzung aller Klassen ändern und zu Schwierigkeiten führen. Diesen Fehler – die Oberschnittstellen haben für eine Konstante unterschiedliche Werte – müsste die Laufzeitumgebung erkennen. Doch das ist nicht möglich, und in der Regel setzt der Compiler die Werte auch direkt in die Aufrufstelle ein, und ein Zugriff auf die Konstantenwerte der Schnittstelle findet nicht mehr statt.