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.
If a method declaration
d1with return typeR1overrides or hides the declaration of another methodd2with return typeR2, thend1must be return-type-substitutable ford2, or a compile-time error occurs.
A method declaration
d1with return typeR1is return-type-substitutable for another methodd2with return typeR2iff any of the following is true:
If
R1isvoidthenR2isvoid.If
R1is a primitive type thenR2is identical toR1.If
R1is a reference type then one of the following is true:
R1, adapted to the type parameters ofd2, is a subtype ofR2.
R1can be converted to a subtype ofR2by unchecked conversion.
d1does not have the same signature asd2, andR1 = |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; }
}