La mia comprensione è la seguente. Iniziamo considerando un'impostazione più semplice. Class Second è astratta e implementa due interfacce, Act e React. Entrambe le interfacce dichiarano un metodo void read() non predefinito. In questo caso, Second eredita più dichiarazioni dello stesso metodo, nessuna implementazione e il compilatore è felice (JLS 8.4.8.4).
interface Act {
void read();
}
interface React {
void read();
}
public abstract class Second implements Act, React {
}
Se uno o entrambi i metodi di interfaccia sono metodi predefiniti, otteniamo un errore di compilazione (JLS 8.4.8.4, 9.4.1.3), a meno che non Seconda eredita il metodo() da una superclasse (JLS 8.4.8 una lettura astratta .4), come nel seguente scenario, dove Second effettivamente finisce per ereditare tre metodi read().
interface Act {
default void read() {}
}
interface React {
void read();
}
abstract class First {
abstract void read();
}
public abstract class Second extends First implements Act, React {
}
In assenza di tale superclasse, Seconda deve dare un'implementazione di read(), impedendo così l'eredità dei metodi contrastanti (GLS 9.4.1.3). Naturalmente, Second deve fare lo stesso se tutti i metodi di interfaccia sono astratti e non vogliamo dichiarare la classe stessa come astratta.
Se Second dà un'implementazione concreta di read(), come nell'esempio seguente, questo metodo non "si riferisce" a uno o l'altro dei metodi di interfaccia: semplicemente sovrascrive e impedisce l'ereditarietà di qualsiasi e tutti i metodi di superinterfaccia con la stessa firma - più precisamente, con una firma che la firma di read() in Second è una sottosegnalazione di - come se esistesse un solo metodo (JLS 8.4.8.1). (In alcuni casi angusti potrebbe essere impossibile per un metodo soddisfare simultaneamente tutti i contratti dei metodi che intende sovrascrivere. James Gosling ne offre un buon esempio nella sezione 4.3.2 dei suoi - e colleghi - il linguaggio di programmazione Java.)
interface Act {
void read();
}
interface React {
void read();
}
public class Second implements Act, React {
@Override
public void read() {}
}
il tuo caso è simile.
interface Act {
void read();
}
abstract class Enact {
void read() {}
}
public class Second extends Enact implements Act {
@Override
public void read() {}
}
L'unica vera differenza è che read() in Enact è un metodo concreto (il fatto che Enact è astratta è irrilevante), ma le cose non cambiano molto: la dichiarazione in Second prevale sia in lettura () in Act e read() in Enact (JLS 8.4.8.1). Allo stesso tempo, è un'implementazione valida dell'interfaccia Act, quindi non c'è davvero alcun problema qui.
Si noti che questo codice potrebbe essere compilato anche se Second non ha sovrascritto read(): Second erediterà read() da Enact e il metodo ereditato sarebbe considerato un'attuazione altrettanto valida di Act (JLS 8.4.8, 8.4 .8.1, 9.4.1.3).
"Sorprendentemente, non c'è errore di compilazione" perché dovrebbe essere? Quali problemi ti aspettavi di affrontare quando si utilizza tale codice? – Pshemo
@Pshemo Sono solo curioso di sapere se il metodo read() si riferisce all'interfaccia o alla classe astratta. È una situazione di ambiguità. Voglio sapere come il compilatore ha risolto questa ambiguità –
"* Sono solo curioso di sapere se il metodo è stato letto() si riferisce a ... * "define" si riferisce a ". – Pshemo