2013-07-18 8 views
12

Ich gehe durch JLS Abschnitt 9.3.1 und ich stieß auf ein interessantes Konzept der ambigen Erbfelder. Dies ist das Beispiel von JLSSchnittstelle zweideutig geerbt Felder

interface BaseColors { 
int RED = 1, GREEN = 2, BLUE = 4; 
} 
interface RainbowColors extends BaseColors { 
int YELLOW = 3, ORANGE = 5, INDIGO = 6, VIOLET = 7; 
} 
interface PrintColors extends BaseColors { 
int YELLOW = 8, CYAN = 16, MAGENTA = 32; 
} 
interface LotsOfColors extends RainbowColors, PrintColors { 
int FUCHSIA = 17, VERMILION = 43, CHARTREUSE = RED+90; 
} 

Es ist möglich, mehrdeutige Felder geerbt zu haben. Aber wenn ich versuche, das Feld zu referenzieren und auf es zuzugreifen, gibt es Kompilierungszeitfehler. Angabe eines Kompilierzeitfehlers für ambivalente Felder Meine Frage ist, warum der Compiler sich nicht zuerst beschwert hat, als das ambivalente Feld vererbt wurde. Warum zur Zugriffszeit gibt es dieses Problem? Wenn wir das gleiche bei der Verwendung von Klassen tun., Erlaubt es. Warum nicht bei Interfaces. Mein Punkt ist, dass es im ersten Moment nicht erlaubt sein sollte. Die Klärung dieses Konzepts wird sehr hilfreich sein.

+2

Ich kenne den historischen Grund nicht, aber beachten Sie, dass in dem Beispiel nicht ** alle ** die Konstanten mehrdeutig sind. Was würde also passieren, wenn Sie die Schnittstellen mischen und ohne die mehrdeutigen Konstanten verwenden möchten? –

Antwort

9

Schnittstelle Felder sind implizit final static geerbt bekommen. Und statische Felder werden niemals vererbt. Sie können ein Feld ausblenden, indem Sie ein neues Feld mit dem gleichen Namen zu definieren, aber Sie müssen nur die Feldnamen mit der entsprechenden Schnittstelle zu qualifizieren, den Konflikt zu lösen:

PrintColors.YELLOW 

oder

RainbowCOlors.YELLOW 

EDIT:

um zu klären (hoffentlich):

der Compiler ermöglicht es Ihnen LotsOfColors.MAGENTA in der Quelle Zusammenarbeit zu nutzen de, obwohl das Feld tatsächlich in PrintColors.MAGENTA definiert ist. Aber das ist nur, um Ihr Leben ein bisschen einfacher zu machen, besonders wenn Sie ein Feld von einer Oberklasse in einer Unterklasse referenzieren.

Im Byte-Code ersetzt der Compiler den Verweis auf LotsOfColors.MAGENTA durch einen Verweis auf PrintColors.MAGENTA. Alles geschieht zur Kompilierungszeit und nicht zur Laufzeit wie für polymorphe Methoden.

Wenn Sie eine Mehrdeutigkeit haben (wie für LotsOfColors.YELLOW), kann der Compiler nicht entscheiden, welches der Felder Sie tatsächlich verwenden möchten. Es kann PrintColors.YELLOW oder RainbowColors.YELLOW sein. Anstatt eine willkürliche Entscheidung zu treffen, erzeugt der Compiler also einen Kompilierungsfehler, der Sie zwingt, die Mehrdeutigkeit aufzulösen. Und Sie beheben die Mehrdeutigkeit im Quellcode, indem Sie den tatsächlichen Klassennamen PrintColors.YELLOW oder RainbowColors.YELLOW angeben.

+0

Nein im obigen Beispiel, wenn ich LotsOfColors.YELLOW verwende. Es gibt mehrdeutigen Fehler zur Kompilierzeit. Das ist, was ich versuche herauszufinden, wenn sie nicht vererbt werden, warum geben sie ein Problem und warum erscheinen sie sogar in LotsOfColors, da sie nicht vererbt werden. – benz

+1

Siehe meine bearbeitete Antwort. –

+0

Meiner Meinung nach war es ein Design-Fehler, dass sie sogar erlaubten, dass "statische" Felder in einer Unterklasse oder einer implementierenden Klasse unqualifiziert waren. –

7

Felder in der Schnittstelle sind standardmäßig public static final so werden sie nicht

+0

Nein im obigen Beispiel, wenn ich LotsOfColors.YELLOW verwende. Es gibt mehrdeutigen Fehler zur Kompilierzeit. Das ist, was ich versuche herauszufinden, wenn sie nicht vererbt werden, warum geben sie ein Problem und warum erscheinen sie sogar in LotsOfColors, da sie nicht vererbt werden. – benz

+0

Während technisch nicht geerbt, können Sie sie indirekt zugreifen, es ist einfach nicht zu empfehlen. Der Fehler ist, wenn zwei der geerbten Schnittstellen beide die gleichen Feldwerte haben, der Compiler nicht weiß, welcher Vorrang hat. –

Verwandte Themen