There is a list of method resolution approach for virtual extension methods explained here. One of the interesting ones is when a class implements multiple interfaces and say 2 of the interfaces have same method signature but different implementations.
also read:
But before that, lets look at a case where the class implements an interface, say I1 and I1 in turn extends another interface I2 and both I1 and I2 have a method with exact same signature. How is the method invocation using the instance of the implementing class handled?
For this lets look at the following example:
public class DefenderMethodsResolution{ public static void main(String[] args){ MySuperClass obj = new MySuperClass(); System.out.println(obj.findProduct(4,5)); } } class MySuperClass implements SpecialMathOperator{ } interface SpecialMathOperator extends MathOperator{ public int findProduct(int a, int b) default{ return MathOperatorHelper.findProductUsingSum(a,b); } } interface MathOperator{ public int findProduct(int a, int b) default{ return MathOperatorHelper.findProduct(a,b); } } class MathOperatorHelper{ public static int findProduct(int a, int b){ System.out.println("Finding product by multiplying"); return a*b; } public static int findProductUsingSum(int a, int b){ int product = 0; System.out.println("Finding product by iterative sum"); for (int i=0;i < b; i++){ product += a; } return product; } }
The output for the above is:
javac DefenderMethodsResolution.java java DefenderMethodsResolution Finding product by iterative sum 20
It clearly shows that in this case the method resolution is handled by neglecting the super Interface and considering the more specific sub Interface provided sub interface is overriding (I dont know the exact term to use here) the method.
When one thinks of Interfaces having code, then the first thing that comes to the mind is “Deadly Diamond of Death“. Lets see how this is tackled by the compiler. Lets go ahead and slightly edit the code to remove the extends from the SpecialMathOperator interface and make MySuperClass implement both the interfaces. [I know this is not the very best examples, but I think good enough to explain the concept?]
public class DefenderMethodsResolution{ public static void main(String[] args){ MySuperClass obj = new MySuperClass(); System.out.println(obj.findProduct(4,5)); } } class MySuperClass implements SpecialMathOperator,MathOperator{ } interface SpecialMathOperator { public int findProduct(int a, int b) default{ return MathOperatorHelper.findProductUsingSum(a,b); } } interface MathOperator{ public int findProduct(int a, int b) default{ return MathOperatorHelper.findProduct(a,b); } } class MathOperatorHelper{ public static int findProduct(int a, int b){ System.out.println("Finding product by multiplying"); return a*b; } public static int findProductUsingSum(int a, int b){ int product = 0; System.out.println("Finding product by iterative sum"); for (int i=0;i < b; i++){ product += a; } return product; } }
Trying to compile the above code we would get:
$javac DefenderMethodsResolution.java javaDefenderMethodsResolution.java:4: error: reference to findProduct is ambiguous, both method findProduct(int,int) in MathOperator and method findProduct(int,int) in SpecialMathOperator match System.out.println(obj.findProduct(4,5)); ^ DefenderMethodsResolution.java:7: error: class MySuperClass inherits unrelated defaults for findProduct(int,int) from types SpecialMathOperator and MathOperator class MySuperClass implements SpecialMathOperator,MathOperator{ ^ 2 errors
So the compiler doesn’t allow the compilation of such code thereby eliminating the Deadly Diamond of Death problem.