Overriding Abstract Methods from Multiple Interfaces, Revisited – Functional-Style Programming

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.

Click here to view code image

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.

Click here to view code image

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.

Click here to view code image

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.
}

Leave a Comment