Si un tipo implementa dos interfaces, y cada interface
una define un método que tiene una firma idéntica, entonces, en efecto, solo hay un método, y no son distinguibles. Si, por ejemplo, los dos métodos tienen tipos de retorno en conflicto, entonces será un error de compilación. Esta es la regla general de herencia, anulación de métodos, ocultación y declaraciones, y se aplica también a posibles conflictos no solo entre 2 interface
métodos heredados , sino también un interface
y un súper class
método, o incluso solo conflictos debido a la eliminación de tipos de genéricos.
Ejemplo de compatibilidad
Aquí hay un ejemplo en el que tiene un interface Gift
, que tiene un present()
método (como en, presentar regalos), y también un interface Guest
, que también tiene un present()
método (como en, el invitado está presente y no ausente).
Presentable johnny
es a la vez a Gift
y a Guest
.
public class InterfaceTest {
interface Gift { void present(); }
interface Guest { void present(); }
interface Presentable extends Gift, Guest { }
public static void main(String[] args) {
Presentable johnny = new Presentable() {
@Override public void present() {
System.out.println("Heeeereee's Johnny!!!");
}
};
johnny.present(); // "Heeeereee's Johnny!!!"
((Gift) johnny).present(); // "Heeeereee's Johnny!!!"
((Guest) johnny).present(); // "Heeeereee's Johnny!!!"
Gift johnnyAsGift = (Gift) johnny;
johnnyAsGift.present(); // "Heeeereee's Johnny!!!"
Guest johnnyAsGuest = (Guest) johnny;
johnnyAsGuest.present(); // "Heeeereee's Johnny!!!"
}
}
El fragmento anterior se compila y se ejecuta.
Tenga en cuenta que solo @Override
hay uno necesario !!! . Esto es porque Gift.present()
y Guest.present()
son " @Override
equivalentes" ( JLS 8.4.2 ).
Por lo tanto, johnny
solo tiene una implementación de present()
, y no importa cómo se trate johnny
, ya sea como Gift
o como a Guest
, solo hay un método para invocar.
Ejemplo de incompatibilidad
Aquí hay un ejemplo donde los dos métodos heredados NO son @Override
equivalentes:
public class InterfaceTest {
interface Gift { void present(); }
interface Guest { boolean present(); }
interface Presentable extends Gift, Guest { } // DOES NOT COMPILE!!!
// "types InterfaceTest.Guest and InterfaceTest.Gift are incompatible;
// both define present(), but with unrelated return types"
}
Esto reitera además que heredar miembros de un interface
debe obedecer la regla general de las declaraciones de miembros. Aquí tenemos Gift
y Guest
definimos present()
con tipos de retorno incompatibles: uno void
al otro boolean
. Por la misma razón por la que no puede un void present()
y un boolean present()
tipo, este ejemplo da como resultado un error de compilación.
Resumen
Puede heredar métodos que sean @Override
equivalentes, sujetos a los requisitos habituales de anulación y ocultación de métodos. Como SON @Override
equivalentes, efectivamente solo hay un método para implementar, y por lo tanto no hay nada para distinguir / seleccionar.
El compilador no tiene que identificar qué método es para qué interfaz, porque una vez que se determina que son @Override
equivalentes, son el mismo método.
Resolver incompatibilidades potenciales puede ser una tarea difícil, pero ese es otro problema por completo.
Referencias
default
métodos en Java 8.Foo
yBar
. Básicamente, su clase implementa una de las interfaces, por ejemploFoo
, y proporciona unBar asBar()
método para devolver una clase interna que implementa la segundaBar
interfaz. No es perfecto ya que su clase no es en última instancia "un bar", pero podría ser útil en algunas circunstancias.Esto se marcó como un duplicado de esta pregunta /programming/24401064/understanding-and-solving-the-diamond-problems-in-java
Necesita Java 8 para obtener un problema de herencia múltiple, pero todavía no es un problema diamon como tal.
Como comenta JB Nizet, puedes arreglar esto, mi anulación.
Sin embargo, no tienes ningún problema con
fuente
hi()
(para corregir la ambigüedad). Por ejemplo, al implementarloA.super.hi()
para elegir implementarlo de la misma manera que A.En lo que respecta al compilador, esos dos métodos son idénticos. Habrá una implementación de ambos.
Esto no es un problema si los dos métodos son efectivamente idénticos, ya que deberían tener la misma implementación. Si son contractualmente diferentes (según la documentación de cada interfaz), tendrá problemas.
fuente
No hay nada que identificar. Las interfaces solo prohíben el nombre y la firma de un método. Si ambas interfaces tienen un método exactamente del mismo nombre y firma, la clase implementadora puede implementar ambos métodos de interfaz con un único método concreto.
Sin embargo, si los contratos semánticos del método de dos interfaces son contradictorios, prácticamente has perdido; no puede implementar ambas interfaces en una sola clase entonces.
fuente
Intente implementar la interfaz como anónima.
fuente
Al igual que en la interfaz, solo estamos declarando métodos, la clase concreta que implementa estas dos interfaces entiende que solo hay un método (como usted describió, ambos tienen el mismo nombre en el tipo de retorno). así que no debería haber ningún problema con él. Podrá definir ese método en una clase concreta.
Pero cuando dos interfaces tienen un método con el mismo nombre pero diferente tipo de retorno e implementa dos métodos en una clase concreta:
Por favor, mire el siguiente código:
cuando el compilador obtiene el método "public void print ()", primero busca en InterfaceA y lo obtiene. Pero aún así da error de tiempo de compilación de que el tipo de retorno no es compatible con el método de InterfaceB.
Entonces se vuelve loco para el compilador.
De esta forma, no podrá implementar dos interfaces que tengan un método con el mismo nombre pero con un tipo de retorno diferente.
fuente
Bueno, si ambos son iguales, no importa. Implementa ambos con un único método concreto por método de interfaz.
fuente