Se um tipo implementa duas interfaces, e cada interface
uma define um método que possui assinatura idêntica, na verdade, existe apenas um método e elas não são distinguíveis. Se, por exemplo, os dois métodos tiverem tipos de retorno conflitantes, será um erro de compilação. Essa é a regra geral de herança, substituição de método, ocultação e declaração, e se aplica também a possíveis conflitos não apenas entre 2 interface
métodos herdados , mas também um método interface
e um super class
, ou mesmo apenas conflitos devido ao apagamento de tipo de genéricos.
Exemplo de compatibilidade
Aqui está um exemplo em que você tem um interface Gift
, que tem um present()
método (como em apresentar presentes), e também um interface Guest
, que também tem um present()
método (como em, o convidado está presente e não está ausente).
Presentable johnny
é a Gift
e 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!!!"
}
}
O trecho acima compila e executa.
Observe que há apenas um @Override
necessário !!! . Isso ocorre Gift.present()
e Guest.present()
é " @Override
-equivalente" ( JLS 8.4.2 ).
Assim, johnny
só tem uma implementação de present()
, e não importa como você trata johnny
, seja como Gift
ou como Guest
, só há um método a ser chamado.
Exemplo de incompatibilidade
Aqui está um exemplo em que os dois métodos herdados NÃO são @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"
}
Isso reitera ainda que a herança de membros de um interface
deve obedecer à regra geral das declarações de membros. Aqui temos Gift
e Guest
definimos present()
com tipos de retorno incompatíveis: um void
o outro boolean
. Pelo mesmo motivo que você não pode um void present()
e um boolean present()
em um tipo, este exemplo resulta em um erro de compilação.
Resumo
Você pode herdar métodos que sejam @Override
equivalentes, sujeitos aos requisitos usuais de substituição e ocultação de métodos. Como são @Override
equivalentes, efetivamente existe apenas um método para implementar e, portanto, não há nada para distinguir / selecionar.
O compilador não precisa identificar qual método é para qual interface, porque uma vez que eles são considerados @Override
equivalentes, eles são o mesmo método.
Resolver possíveis incompatibilidades pode ser uma tarefa complicada, mas isso é outra questão.
Referências