Overriding Abstract Methods from Multiple Interfaces, Revisited
A general discussion on overriding abstract methods from multiple superinterfaces can be found in §11.12, p. 621. In general, an interface can inherit multiple abstract methods from its superinterfaces, but a functional interface can only have a single abstract method. Note that superinterfaces need not be functional interfaces. It is even more imperative to use the @FunctionalInterface annotation to catch any inadvertent errors when a functional interface inherits abstract methods from multiple superinterfaces.
In the code below, the compiler does not flag any error in the declaration of the sub-interface ContractZ. It is perfectly valid for the subinterface to inherit the doIt() method from each of its superinterfaces, as the two method declarations will be overloaded.
interface ContractX { void doIt(int i); }
interface ContractY { void doIt(double d); }
interface ContractZ extends ContractX, ContractY {
@Override void doIt(int d); // Can be omitted.
@Override void doIt(double d); // Can be omitted.
}
Trying to declare the subinterface ContractZ as a functional interface, however, does not work. The multiple abstract methods inherited by the ContractZ are not override-equivalent—their signatures are different—and there is no single method that can override these methods, thus disqualifying ContractZ as a functional interface.
interface ContractX { void doIt(int i); }
interface ContractY { void doIt(double d); }
@FunctionalInterface interface ContractZ // Compile-time error!
extends ContractX, ContractY {
@Override void doIt(int d); // Compile-time error!
@Override void doIt(double d); // Compile-time error!
}
In the code below, the subinterface Features<T> at (1) is a functional interface, as the declarations of the abstract method flatten() in its superinterfaces are override-equivalent. Any declaration of the abstract method flatten() can represent the abstract methods from the superinterfaces in the subinterface.
interface Feature1<R> { void flatten(List<R> plist); }
interface Feature2<S> { void flatten(List<S> plist); }
@FunctionalInterface
interface Features<T> extends Feature1<T>, Feature2<T> { // (1)
@Override void flatten(List<T> plist); // Can be omitted.
}