I understand that if a class implements multiple interfaces containing default methods of same name, then we need to override that method in the child class so as to explicitly define what my method will do.
Problem is, see the below code :
interface A {
default void print() {
System.out.println(" In interface A ");
}
}
interface B {
default String print() {
return "In interface B";
}
}
public class C implements A, B {
@Override
public String print() {
return "In class C";
}
public static void main(String arg[]) {
// Other funny things
}
}
Now interface A and B both have a default method with name ‘print’ but I want to override the print method of interface B – the one that returns a string and leave A’s print as is. But this code doesn’t compile giving this :
Overrides A.print
The return type is incompatible with A.print()
Clearly compiler is trying to override A’s print method, and I have no idea why !
Solution:
This is not possible.
8.4.8.3:
If a method declaration d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type-substitutable for d2, or a compile-time error occurs.
8.4.5:
A method declaration d1 with return type R1 is return-type-substitutable for another method d2 with return type R2 iff any of the following is true:
-
If R1 is void then R2 is void.
-
If R1 is a primitive type then R2 is identical to R1.
-
If R1 is a reference type then one of the following is true:
-
R1, adapted to the type parameters of d2, is a subtype of R2.
-
R1 can be converted to a subtype of R2 by unchecked conversion.
-
d1 does not have the same signature as d2, and R1 = |R2|.
In other words, void, primitive- and reference-returning methods may only override and be overridden by methods of that same respective category. A void method may only override another void method, a reference-returning method may only override another reference-returning method, and so on.
One possible solution to the problem you’re having could be to use composition instead of inheritance:
class C {
private A a = ...;
private B b = ...;
public A getA() { return a; }
public B getB() { return b; }
}