8 Stimmen

Rufen Sie denselben Methodennamen aus zwei verschiedenen Schnittstellen auf - Java

Java erlaubt nicht die Mehrfachvererbung zum Schutz vor dem Diamantenproblem. Es verwendet Schnittstellen, um dieses Problem zu lösen.

Dann der Fall der Verwendung von Schnittstellen, sagen wir

interface A{
run();
}

interface B{
run();
}

class C implements A, B{
run() {}   //Welche Schnittstelle verwenden wir?
}

Wenn wir die Methode run() in der Klasse C aufrufen, wie können wir bestimmen, welche Schnittstelle wir verwenden?

10voto

Akira Punkte 3873

Sie ​​tun es nicht. Und es ist nicht wichtig, da die Implementierung nicht an der Schnittstelle, sondern an der Klasse erfolgt. Daher ist die Implementierung eindeutig. Keine Mehrdeutigkeit.

Was wichtig ist, ist, ob jede Deklaration einen anderen Rückgabetyp haben möchte:

interface A{
    void run();
}

interface B{
    String run();
}

class C implements A, B{
    ???? run() {}
}

Dies ist der einzige Fall, in dem Sie Probleme mit mehreren Schnittstellen in Java haben können.

7voto

Vincent Ramdhanie Punkte 100426

Es spielt keine Rolle. Der Zweck der Schnittstelle besteht darin anzugeben, dass die Klasse C eine Methode run() hat. Du kannst dich darauf verlassen, dass diese Methode vorhanden ist.

Auch wenn sowohl A als auch B die run-Methode spezifizieren, wird sie nur einmal implementiert, so dass es keinen Konflikt gibt.

Wenn du sagst, dass du eine Schnittstelle verwendest, bedeutet das wirklich, wie deine Objekte deklariert sind:

   A myobject = new C();
   myobject.run();

vs

   B myObject = new C();
   myobject.run();

Im ersten Fall "verwendest" du die A-Schnittstelle, d. h. dein Code geht davon aus, dass das myobject-Objekt vom Typ A ist und eine Methode namens run() hat. Im zweiten Fall "verwendest" du die Schnittstelle B.

3voto

Reuben Tanner Punkte 4880

Wenn ein Typ zwei Schnittstellen implementiert und jede Schnittstelle eine Methode definiert, die eine identische Signatur hat, dann gibt es effektiv nur eine Methode und sie sind nicht unterscheidbar. Wenn beispielsweise die beiden Methoden inkompatible Rückgabetypen haben, wird es zu einem Kompilierfehler. Dies ist die allgemeine Regel für Vererbung, Methodenüberschreibung, Verdeckung und Deklarationen und gilt auch für mögliche Konflikte nicht nur zwischen 2 geerbten Schnittstellenmethoden, sondern auch zwischen einer Schnittstelle und einer übergeordneten Klassenmethode oder sogar nur Konflikte aufgrund der Typlöschung von Generika.

Kompatibilitätsbeispiel

Hier ist ein Beispiel, bei dem Sie eine Schnittstelle Geschenk haben, die eine present() Methode hat (als Geschenke präsentieren) und auch eine Schnittstelle Gast haben, die ebenfalls eine present() Methode hat (als Gast anwesend und nicht abwesend ist).

Geschenkbarer Johnny ist sowohl ein Geschenk als auch ein Gast.

public class InterfaceTest {
    interface Geschenk { void present(); }
    interface Gast { void present(); }

    interface Vorzeigbares extends Geschenk, Gast { }

    public static void main(String[] args) {
        Vorzeigbares johnny = new Vorzeigbares() {
            @Override public void present() {
                System.out.println("Heeeereee's Johnny!!!");
            }
        };
        johnny.present();                     // "Heeeereee's Johnny!!!"

        ((Geschenk) johnny).present();            // "Heeeereee's Johnny!!!"
        ((Gast) johnny).present();           // "Heeeereee's Johnny!!!"

        Geschenk johnnyAlsGeschenk = (Geschenk) johnny;
        johnnyAlsGeschenk.present();               // "Heeeereee's Johnny!!!"

        Gast johnnyAlsGast = (Gast) johnny;
        johnnyAlsGast.present();              // "Heeeereee's Johnny!!!"
    }
}

Der obige Ausschnitt wird kompiliert und ausgeführt.

Beachten Sie, dass nur ein @Override erforderlich ist!!!. Dies liegt daran, dass Geschenk.present() und Gast.present() "@Override-äquivalent" sind (JLS 8.4.2).

Daher hat Johnny nur eine Implementierung von present() und es spielt keine Rolle, wie Sie Johnny behandeln, ob als Geschenk oder als Gast, es gibt nur eine Methode, die aufgerufen werden kann.

Inkompatibilitätsbeispiel

Hier ist ein Beispiel, in dem die beiden geerbten Methoden NICHT @Override-äquivalent sind:

public class InterfaceTest {
    interface Geschenk { void present(); }
    interface Gast { boolean present(); }

    interface Vorzeigbares extends Geschenk, Gast { } // KOMPILIERT NICHT!!!
    // "Typen InterfaceTest.Gast und InterfaceTest.Geschenk sind nicht kompatibel;
    //  beide definieren present(), aber mit nicht verwandten Rückgabetypen"
}

Dies unterstreicht weiterhin, dass das Erben von Elementen aus einer Schnittstelle der allgemeinen Regel für Elementdeklarationen entsprechen muss. Hier definieren Geschenk und Gast present() mit unvereinbaren Rückgabetypen: ein void und ein boolean. Aus demselben Grund, aus dem Sie keine void present() und eine boolean present() in einem Typ haben können, führt dieses Beispiel zu einem Kompilierfehler.

Zusammenfassung

Sie können Methoden erben, die @Override-äquivalent sind, unterliegen den üblichen Anforderungen für Methodenüberschreibung und -verdeckung. Da sie @Override-äquivalent sind, gibt es effektiv nur eine Methode zu implementieren, und daher gibt es nichts zu unterscheiden/auszuwählen.

Der Compiler muss nicht identifizieren, welche Methode für welche Schnittstelle ist, denn sobald sie als @Override-äquivalent bestimmt werden, handelt es sich um dieselbe Methode.

Die Behebung möglicher Inkompatibilitäten kann eine knifflige Aufgabe sein, aber das ist ein ganz anderes Thema.

Referenzen

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.8.4

1voto

Basant Singh Punkte 5606

Auch wenn Sie mehrere Schnittstellen mit denselben Methodendeklarationen implementieren, haben Sie in Ihrer Klasse nur eine Definition dieser Methode. Es gibt also keine Mehrdeutigkeit, da es nur eine Methode gibt, die aufgerufen werden kann.

1voto

blalasaadri Punkte 5975

Sie können es nicht erkennen; es spielt jedoch auch keine Rolle, da Schnittstellen keine Funktionalität haben.

Dies wird sich geringfügig ändern, wenn Java 8 herauskommt, da Schnittstellen dann Standardimplementierungen von Funktionen haben können. Wenn es mehr als eine Standardimplementierung gibt, kann es Unklarheiten geben. Wie dies gelöst wird, wird in der Frage erklärt Sind Standardimplementierungen in JDK 8 eine Form von Mehrfachvererbung in Java?.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X