2010-12-23 12 views
1

Kürzlich stieß man auf ein interessantes Feature, das jedoch zu einer unerwarteten Ausgabe von Eclipse "add unimplemented methods" führen kann. Was ist der "googl-fähige" Name des Sprachkonzepts hinter dieser "gelegentlichen impliziten Implementierung"?java accidential implizite Schnittstellenimplementierung

würde ich nicht erwarten, dass der folgende Code zu kompilieren, aber es tat und arbeitet

interface CallmeIfc { 
    public void callme(); 
} 

class CallmeCode { 
    public void callme() { 
    // implementation 
    } 
} 

class CallmeImpl extends CallmeCode implements CallmeIfc { 
    // empty class body 
} 

public static void main(String[] args) { 
    CallmeIfc me = (CallmeIfc) new CallmeImpl(); 
    me.callme(); // calls CallmeCode.callme() 
} 
+2

Um ... Vererbung? Virtuelle Funktionstabellen? – OrangeDog

+0

Ihr 'CallMeImpl' implementiert' public void callme() 'durch Übernahme von' CallMeCode'. Das ist alles, es gibt keinen speziellen Namen dafür. –

+1

@Joonas Pulakka - Ich habe den Namen dafür, "Subcontracting", Impl ist genau wie eine Agentur, dient einem Kunden (Schnittstelle) von einem Auftragnehmer (Super-Klasse) ohne sie sich kennen zu lassen :) – bobah

Antwort

1

Eigentlich sieht es wie ein Compiler Fehler zu mir: Die Java Language Specification writes:

Eine Instanzmethode m1 in einer Klasse deklariert C überschreibt eine andere Instanz Methode, m2, in der Klasse erklärt A iff alle folgenden Aussagen sind wahr:

  • C ist eine Unterklasse von A.
  • Die Signatur m1 ist eine Untersignatur (§8.4.2) der Signatur m2.
  • Entweder
    • m2 ist öffentlich, geschützt oder mit Standardzugriff im selben Paket wie C deklarierte oder
    • m1 überschreibt ein Verfahren m3, m3 verschieden von m1, m3 verschieden von m2, so dass m3 Überschreibungen m2 .

In Ihrem Fall ist die erste Bedingung nicht erfüllt: Die Methode callme in Klasse deklariert ist CallMeCode, das kein Subtyp von CallmeIfc ist.

Bearbeiten: Bobah hat recht, die Spec unterscheidet zwischen implementieren und überschreiben.In der Tat, es mandates tatsächlich das beobachtete Verhalten:

Es sei denn, die Klasse abstrakt deklariert werden, wobei die Erklärungen aller Methode Mitglieder jeder direkten Superschnitt werden muss, entweder durch eine Erklärung in dieser Klasse implementiert oder durch ein existierendes Verfahren Erklärung vom direkten Überklasse geerbt, weil eine Klasse, die nicht abstrakt ist nicht gestattet zu abstrahieren Methoden haben

Die Spezifikation erklärt nicht warum.

+0

Ich bin mir nicht ganz sicher, ob eine Klasse, die eine Schnittstelle implementiert, eine "Unterklasse" dieser Schnittstelle ist und die Implementierung einer Schnittstellenmethode "überschreibt". Was wir also beobachten können, ist ein recht allgemeingültiges Compiler-Verhalten. – bobah

+0

Sie haben Recht. Ich habe das entsprechend bearbeitet. – meriton

2

In CallmeImpl, die Öffentlichkeit callme() -Methode von CallmeCode vererbt wird, so CallmeImpl den Vertrag in der CallmeIfc definiert respektiert .

Dann können Sie in Ihrer main() - Methode eine Unterklasseninstanz (CallmeImpl) einer Superklassen- oder Superinterface-Referenz zuweisen - in diesem speziellen Fall der "me" -Referenz vom Typ CallmeIfc (Sie haben einen Tippfehler hier, BTW).

+0

Welchen Teil meiner Frage haben Sie beantwortet? – bobah

+3

Nun, ich sehe nicht, was Sie in diesem Code und seinem Verhalten "unerwartet" finden. Es ist sehr Standard OO Design. Also habe ich versucht, die OO-Konzepte zu erklären, die es funktionieren lassen. Hier sind die "googlefähigen Begriffe" Vererbung und Polymorphie. Wenn Sie eine genauere Frage haben, werde ich gerne versuchen, es zu beantworten. –

+1

Ich bin nicht sicher, dass Schnittstelle und Implementierungscode nicht auf dem gleichen Stammpfad im Vererbungsbaum ist "sehr Standard-OO-Design". Als ich eine Frage stellte, erwartete ich eine Antwort wie "ah! Das ist einfach, es heißt xxx, funktioniert wie yyy, deshalb ist es in Java anders als in C++ möglich". – bobah

1

Obwohl die CallmeCode-Klasse die CallmeIfc-Schnittstelle nicht implementiert, stellt sie die erforderliche Implementierung bereit. Es ist, als ob die Klasse CallmeCode die Schnittstelle implementiert. Es wäre auch mit diesem Code gearbeitet:

interface CallmeIfc { 
    public void callme(); 
} 

class CallmeCode implements CallmeIfc { 
    public void callme() { 
     // implementation 
    } 
} 

class CallmeImpl extends CallmeCode implements CallmeIfc { 
    // empty class body 
} 

In Ihrem Fall ist es in Ordnung, weil Klasse CallmeCode ein Verfahren callme hat. Wenn die Methode anders benannt worden wäre, würde sie nicht kompiliert werden.

Verwandte Themen