Reputation: 15110
Two interfaces with same method names and signatures. But implemented by a single class then how the compiler will identify the which method is for which interface?
Ex:
interface A{
int f();
}
interface B{
int f();
}
class Test implements A, B{
public static void main(String... args) throws Exception{
}
@Override
public int f() { // from which interface A or B
return 0;
}
}
Upvotes: 315
Views: 275832
Reputation: 652
Adding one more example in case of names are same but different return type. the only way to resolve this issue is use one interface and define function in different class. Meaning of this example was to tell it's not possible to resolve this scenario by implementing both interfaces.
Consider below example
public interface Interface1 {
// create a method
public void show();
}
public interface Interface2 {
// create method with same name & signature but
// different return type
public String show();
}
// implement only 1 interface
public class Case3_1 implements Interface1 {
// override method of that interface
@Override public void show()
{
System.out.println("void show()");
}
public static void main(String[] args)
{
// create object
Case3_1 obj = new Case3_1();
// calling method
obj.show();
}
}
Output
void show()
// implement only 1 interface
public class Case3_2 implements Interface2 {
// override the method of interface
@Override public String show() { return "String show()"; }
public static void main(String[] args)
{
// object creation
Case3_2 obj = new Case3_2();
// calling method
String res = obj.show();
// printing returned result
System.out.println(res);
}
}
Output
String show()
Explanation: In this case, we can’t implement both interfaces in the same class because an error can be thrown due to ambiguity between them. So we need to create a different class to implement Interface2.
ref https://www.geeksforgeeks.org/interface-naming-conflicts-in-java/
Upvotes: 0
Reputation: 1376
APPROACH 1:
App.java
-
public class App {
public static void main(String[] args) {
TestInterface1 testInterface1 = new TestInterface1();
TestInterface2 testInterface2 = new TestInterface2();
testInterface1.draw();
testInterface2.draw();
}
}
TestInterface1.java
-
public class TestInterface1 implements Circle {
}
TestInterface2.java
-
public class TestInterface2 implements Rectangle {
}
Circle.java
-
public interface Circle extends Drawable {
@Override
default void draw() {
System.out.println("Drawing circle");
}
}
Rectangle.java
-
public interface Rectangle extends Drawable {
@Override
default void draw() {
System.out.println("Drawing rectangle");
}
}
Drawable.java
-
public interface Drawable {
default void draw() {
System.out.println("Drawing");
}
}
Output -
Drawing circle
Drawing rectangle
APPROACH 2:
App.java
-
public class App {
public static void main(String[] args) {
Circle circle = new Circle() {
};
Rectangle rectangle = new Rectangle() {
};
circle.draw();
rectangle.draw();
}
}
Circle.java
-
public interface Circle extends Drawable {
@Override
default void draw() {
System.out.println("Drawing circle");
}
}
Rectangle.java
-
public interface Rectangle extends Drawable {
@Override
default void draw() {
System.out.println("Drawing rectangle");
}
}
Drawable.java
-
public interface Drawable {
default void draw() {
System.out.println("Drawing");
}
}
Output -
Drawing circle
Drawing rectangle
Upvotes: -2
Reputation: 533890
This was marked as a duplicate to this question https://stackoverflow.com/questions/24401064/understanding-and-solving-the-diamond-problems-in-java
You need Java 8 to get a multiple inheritance problem, but it is still not a diamon problem as such.
interface A {
default void hi() { System.out.println("A"); }
}
interface B {
default void hi() { System.out.println("B"); }
}
class AB implements A, B { // won't compile
}
new AB().hi(); // won't compile.
As JB Nizet comments you can fix this my overriding.
class AB implements A, B {
public void hi() { A.super.hi(); }
}
However, you don't have a problem with
interface D extends A { }
interface E extends A { }
interface F extends A {
default void hi() { System.out.println("F"); }
}
class DE implement D, E { }
new DE().hi(); // prints A
class DEF implement D, E, F { }
new DEF().hi(); // prints F as it is closer in the heirarchy than A.
Upvotes: 44
Reputation: 51
As in interface,we are just declaring methods,concrete class which implements these both interfaces understands is that there is only one method(as you described both have same name in return type). so there should not be an issue with it.You will be able to define that method in concrete class.
But when two interface have a method with the same name but different return type and you implement two methods in concrete class:
Please look at below code:
public interface InterfaceA {
public void print();
}
public interface InterfaceB {
public int print();
}
public class ClassAB implements InterfaceA, InterfaceB {
public void print()
{
System.out.println("Inside InterfaceA");
}
public int print()
{
System.out.println("Inside InterfaceB");
return 5;
}
}
when compiler gets method "public void print()" it first looks in InterfaceA and it gets it.But still it gives compile time error that return type is not compatible with method of InterfaceB.
So it goes haywire for compiler.
In this way, you will not be able to implement two interface having a method of same name but different return type.
Upvotes: 5
Reputation: 4695
Try implementing the interface as anonymous.
public class MyClass extends MySuperClass implements MyInterface{
MyInterface myInterface = new MyInterface(){
/* Overrided method from interface */
@override
public void method1(){
}
};
/* Overrided method from superclass*/
@override
public void method1(){
}
}
Upvotes: 4
Reputation: 384016
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.
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.
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.
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.
Upvotes: 441
Reputation: 346546
There is nothing to identify. Interfaces only proscribe a method name and signature. If both interfaces have a method of exactly the same name and signature, the implementing class can implement both interface methods with a single concrete method.
However, if the semantic contracts of the two interface method are contradicting, you've pretty much lost; you cannot implement both interfaces in a single class then.
Upvotes: 19
Reputation: 9446
As far as the compiler is concerned, those two methods are identical. There will be one implementation of both.
This isn't a problem if the two methods are effectively identical, in that they should have the same implementation. If they are contractually different (as per the documentation for each interface), you'll be in trouble.
Upvotes: 23
Reputation: 16799
Well if they are both the same it doesn't matter. It implements both of them with a single concrete method per interface method.
Upvotes: 5