Se un tipo implementa due interfacce e ognuna interface
definisce un metodo con firma identica, in effetti esiste un solo metodo e non sono distinguibili. Se, per esempio, i due metodi hanno tipi di ritorno in conflitto, allora si tratterà di un errore di compilazione. Questa è la regola generale dell'ereditarietà, dell'override del metodo, del nascondimento e delle dichiarazioni, e si applica anche a possibili conflitti non solo tra 2 interface
metodi ereditati , ma anche un interface
e un class
metodo super , o anche solo conflitti dovuti alla cancellazione del tipo di generici.
Esempio di compatibilità
Ecco un esempio in cui hai un interface Gift
, che ha un present()
metodo (come in, presentare regali), e anche un interface Guest
, che ha anche un present()
metodo (come in, l'ospite è presente e non assente).
Presentable johnny
è sia a Gift
che 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!!!"
}
}
Lo snippet sopra riportato viene compilato ed eseguito.
Si noti che ce n'è solo uno @Override
necessario !!! . Questo perché Gift.present()
e Guest.present()
sono " @Override
equivalenti" ( JLS 8.4.2 ).
Quindi, johnny
ha solo un'implementazione di present()
, e non importa come tratti johnny
, sia come Gift
che come Guest
, c'è solo un metodo da invocare.
Esempio di incompatibilità
Ecco un esempio in cui i due metodi ereditati NON sono @Override
equivalenti:
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"
}
Ciò ribadisce inoltre che ereditare i membri da una interface
deve obbedire alla regola generale delle dichiarazioni dei membri. Qui abbiamo Gift
e Guest
definiamo present()
con tipi di ritorno incompatibili: uno void
l'altro boolean
. Per lo stesso motivo per cui non è possibile un void present()
e un boolean present()
tipo, questo esempio genera un errore di compilazione.
Sommario
È possibile ereditare metodi @Override
equivalenti, soggetti ai normali requisiti di sostituzione e occlusione del metodo. Dal momento che SONO @Override
equivalenti, in effetti esiste solo un metodo da implementare, e quindi non c'è nulla da distinguere / selezionare.
Il compilatore non deve identificare quale metodo è per quale interfaccia, perché una volta che sono determinati per essere @Override
equivalenti, sono lo stesso metodo.
Risolvere potenziali incompatibilità può essere un compito complicato, ma questo è un altro problema.
Riferimenti