Implementing Two Interfaces in a Class with Same Method. Which Interface Method Is Overridden

Implementing two interfaces in a class with same method. Which interface method is overridden?

If a type implements two interfaces, and each interface define a method that has identical signature, then in effect there is only one method, and they are not distinguishable. If, say, the two methods have conflicting return types, then it will be a compilation error. This is the general rule of inheritance, method overriding, hiding, and declarations, and applies also to possible conflicts not only between 2 inherited interface methods, but also an interface and a super class method, or even just conflicts due to type erasure of generics.


Compatibility example

Here's an example where you have an interface Gift, which has a present() method (as in, presenting gifts), and also an interface Guest, which also has a present() method (as in, the guest is present and not absent).

Presentable johnny is both a Gift and a Guest.

public class InterfaceTest {
interface Gift { void present(); }
interface Guest { void present(); }

interface Presentable extends Gift, Guest { }

public static void main(String[] args) {
Presentable johnny = new Presentable() {
@Override public void present() {
System.out.println("Heeeereee's Johnny!!!");
}
};
johnny.present(); // "Heeeereee's Johnny!!!"

((Gift) johnny).present(); // "Heeeereee's Johnny!!!"
((Guest) johnny).present(); // "Heeeereee's Johnny!!!"

Gift johnnyAsGift = (Gift) johnny;
johnnyAsGift.present(); // "Heeeereee's Johnny!!!"

Guest johnnyAsGuest = (Guest) johnny;
johnnyAsGuest.present(); // "Heeeereee's Johnny!!!"
}
}

The above snippet compiles and runs.

Note that there is only one @Override necessary!!!. This is because Gift.present() and Guest.present() are "@Override-equivalent" (JLS 8.4.2).

Thus, johnny only has one implementation of present(), and it doesn't matter how you treat johnny, whether as a Gift or as a Guest, there is only one method to invoke.


Incompatibility example

Here's an example where the two inherited methods are NOT @Override-equivalent:

public class InterfaceTest {
interface Gift { void present(); }
interface Guest { boolean present(); }

interface Presentable extends Gift, Guest { } // DOES NOT COMPILE!!!
// "types InterfaceTest.Guest and InterfaceTest.Gift are incompatible;
// both define present(), but with unrelated return types"
}

This further reiterates that inheriting members from an interface must obey the general rule of member declarations. Here we have Gift and Guest define present() with incompatible return types: one void the other boolean. For the same reason that you can't an void present() and a boolean present() in one type, this example results in a compilation error.


Summary

You can inherit methods that are @Override-equivalent, subject to the usual requirements of method overriding and hiding. Since they ARE @Override-equivalent, effectively there is only one method to implement, and thus there's nothing to distinguish/select from.

The compiler does not have to identify which method is for which interface, because once they are determined to be @Override-equivalent, they're the same method.

Resolving potential incompatibilities may be a tricky task, but that's another issue altogether.

References

  • JLS 8.4.2 Method Signature
  • JLS 8.4.8 Inheritance, Overriding, and Hiding
  • JLS 8.4.8.3 Requirements in Overriding and Hiding
  • JLS 8.4.8.4 Inheriting Methods with Override-Equivalent Signatures

    • "It is possible for a class to inherit multiple methods with override-equivalent signatures."

Two Interface with Same Method Name - Implementation of Methods

For 1, the answer is yes. It's enough to provide one implementation for the method in the class for both interfaces to be automatically implemented.

For 2, if you need to have both methods, then your class should not implement both interfaces. However, there's a trick you can use:

interface IOne {

void method();
}

interface ITwo {

void method();
}

public class A
implements IOne, ITwo {

// Anonymous inner class that implements ony IOne
private final IOne one = new IOne() {

@Override
public void method() {
System.out.println("IOne");
}
};

// Anonymous inner class that implements ony ITwo
private final ITwo two = new ITwo() {

@Override
public void method() {
System.out.println("ITwo");
}
};

@Override
public void method() {
System.out.println("A");
}

// Method that delegates to IOne
public void methodIOne() {
this.one.method();
}

// Method that delegates to ITwo
public void methodITwo() {
this.two.method();
}
}

Testing code:

A a = new A();
a.method(); // A
a.methodIOne(); // IOne
a.methodITwo(); // ITwo

Class A doesn't need to implement both interfaces. In that case, just don't implement method() on A and keep only the anonymous inner classes.

In java 8, implementing two interfaces with same name method, first method dont have body, second does

It's weird syntax, but it is available:

class ChildClass implements Interface01, Interface02 {

public void method() { //override method from Interface01

Interface02.super.method(); // calling method from Interface02
}
}

You can use this here. You can also use it if both I1 and I2 have a default method - then your ChildClass wouldn't compile either (javac forces you to explicitly pick which of the two impls you want, or if you want to write an entirely new one - that's because java, by the design, does not want the order in which you listed your interfaces to change what your code means).

Two interfaces with same method name, what happens when I override?

In this case it will be like there is only one method. It will override "both" methods in this case because they have the exact same signatures. If the methods had different signatures (return type or something) then there would be a problem. Check out this answer here

For Example:

public class MyClass implements A, B {

@Override
public void mymethod(){
System.out.println("hello world");
}

}
...

public interface A {
void mymethod();
}
...

public interface B {
String mymethod();
}

This would cause a problem...

Implementing multiple interfaces having same method

Because it's an interface there is no harm done. You're basically using a blueprint for your C class by implementing A and B. Both A and B say that C should implement a method called test()

Your C class implements that method, so the interfaces have done their job.

It's basically your C class saying: "Oh hey, I need to implement test() because of interface A" and you implement it. Then your C class says "Oh hey, I need to implement test() again because of interface B" and it sees that there is already a method called test() implemented so it's satisfied.

You can also find more information here: JLS §8.4.8.4

Kotlin, Implementing two interfaces with same method and have default values

You can not do this. because the implementor method can not have a default value. and if you use C().f() how the compiler is going to know use which default value?
because C() is An A and it is Also a B.

C().f() has to call C.f(true) because true is the default value in A.
and
C().f() also has to call C().f(false) because false is default value in B.
so it is a conflict and it is not allowed.

You can do something like this to achieve what you want :

interface A {
fun f(b)
fun f(){f(true)}
}

interface B {
fun f(b)
fun f(){f(false)}
}

class C : A, B {

override fun f(b: Boolean) {

}
override fun f() {
// now you can define which default value is used for class C
// You can define either true or false
f(true)
}

}

Name Clash, override fail, on a class implementing two interfaces with same erasure

Ok, I found a way to solve it. It's clumpsy, but it's the easier one if the architecture is not very complex, inspired by my Why can't I extend an interface "generic method" and narrow its type to my inherited interface "class generic"? own answer:

public class OutsourcableDeveloper<C> 
extends Developer<C>
implements Rentable{

/* This might not be needed if we don't need to extract C from taxes parameter */
final Class<C> currencyClass;
public OutsourcableDeveloper(Class<C> currencyClass){ this.currencyClass = currencyClass;}

@Override
public Rate<C> getRate(@SuppressWarnings("rawtypes") Taxes taxes){
try{
C taxesCurrency = (C) currencyClass.cast(taxes.getCurrency()); //IF actually needed getting the typed instance
return new Rate<C>(taxesCurrency); //Or whatever processing
} catch (ClassCastException e){
throw new UnsupportedOperationException("OutsourcableDeveloper does not accept taxes in a currency that its not hims");
}
}
}

It is also possible to play with "extends Developer" without the generic type, so it is implictly raw. but we loose typing for the non-conflicting methods as well

How to implement an override method of implemented interfaces with the same signature in java. And give different implementations for each interface

Since the method is not aware of the context (a.printInterfaceName() or b.printInterfaceName()), it will not be possible to distinguish between both of them and print INTERFACE-A or INTERFACE-B.

As far as I know, neither reflection nor instanceof can do the trick. Having default Methods in the Interfaces wont work either.

Maybe you can write more about your intention, so that a different solution can be suggested?



Related Topics



Leave a reply



Submit