8

Java doesn't allow the multiple inheritance to protect diamond problem. It uses interface to take care of this problem.

Then the case of using interface, let's say

interface A{
run();
}

interface B{
run();
}

class C implements A, B{
run() {}   //Which interface we are using?
}

When we call the method run() in the class C, how can we determine which interface we are using?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
Taewan
  • 1,167
  • 4
  • 15
  • 25
  • 3
    And more importantly, it doesn't matter. – Kayaman Nov 13 '13 at 16:39
  • Note that you don't have return types in your method declarations at the moment. If the two interface `run` methods declare incompatible return types, you won't be able to implement the interface. – Jon Skeet Nov 13 '13 at 16:41
  • Interfaces are contracts, and have no (implementation) code at all. In other words: you are declaring a "name" that must be implemented elsewhere. – PeterMmm Nov 13 '13 at 16:41

7 Answers7

10

You don´t. And it does not matter, since the implementation is not on the interface but on the class. So the implementation is unique. No ambiguity.

What does matter is if each declaration wants to have a different return type:

interface A{
    void run();
}

interface B{
    String run();
}

class C implements A, B{
    ???? run() {}
}

This is the only way you can have problems with multiple interfaces in Java.

Akira
  • 4,001
  • 1
  • 16
  • 24
  • In class C you will have to run() methods, one with void and one with String. – Ionut Negru Jun 20 '14 at 04:21
  • what if both have void return type ? – Aman Gupta Jul 12 '14 at 00:20
  • more importantly, if return type is also same then I think, it follows first come first serve rule, it will override from the interface first declared after implements keyword – Aman Gupta Jul 12 '14 at 00:24
  • 1
    @agpt, you are making a confusion. You do not override a method of an interface since the method body does not exist yet. You simply implement a method using the signature provided by the interface. There is no first serve rule since you are not replacing anything. – Akira Jul 14 '14 at 12:39
  • @IonutNegru, you can't have two methods with the same name, same arguments, and different return types. Think of a method signature as a key on a keyboard. Once you have pressed the key (chosen the name and the arguments) the caller has to sit down waiting for some result to come back. Even if you have two keys called "run", it does not make sense that each of them does a different thing when invoked. – Akira Jul 14 '14 at 12:45
  • @Akira I mean this.. `void run()` in interface A and `void run()` in interface B. now which method will be overridden inside class C in above mention order `implements A, B`.. I hope this time i am bit clear – Aman Gupta Jul 14 '14 at 13:59
  • If you try to compile my code, you will see a compilation exception. That situation causes Javac to give up compiling. The OP's code does not compile since it has no return types. Now, if both A and B have the same signature for run(), then you implement both at the same time. It is not either A or B, but both. In other words, the following: `A a = new C(); a.run(); B b = new C(); b.run()` will run the same method twice. – Akira Jul 14 '14 at 14:07
7

It does not matter. The purpose of the interface is to indicate that the class C has a method run(). You can depend on that method being there.

Even though both A and B specify the run method it is only implemented once so there is no conflict.

When you say you are using an interface it really means how your objects are declared:

   A myobject = new C();
   myobject.run();

vs

   B myObject = new C();
   myobject.run();

In the first case you are "using" the A interface, that is, your code is assuming that the myobject Object is of type A and that it has a method called run(). In the second case you are "using" the interface B.

Vincent Ramdhanie
  • 102,349
  • 23
  • 137
  • 192
3

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

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.8.4

Reuben Tanner
  • 5,229
  • 3
  • 31
  • 46
1

Even if you implement multiple interfaces with same method declarations, you will only have one definition of that method in your class. So, there isn't any ambiguity here since there is only one method to call.

Basant Singh
  • 5,736
  • 2
  • 28
  • 49
1

You can't tell; however it doesn't matter either, as interfaces have no functionality.

This will change slightly when Java 8 comes out as then interfaces can have default implementations of functions; if there's more than one default implementation then there might be ambiquity. How this is solved is explained in the question Are defaults in JDK 8 a form of multiple inheritance in Java?.

Community
  • 1
  • 1
blalasaadri
  • 5,990
  • 5
  • 38
  • 58
0

Your question doesn't make much sense. Let's take a realistic example. A Human can cry. An AnimalBaby can cry. Now you have an instance John which is both a Human and an AnimalBaby, and you make it cry. What happens? John cries. The fact that it implements the cry() methods of both interfaces doesn't change what crying means and does for John.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
0

Both. C inherited two methods from two interfaces (which happen to be override-equivalent (8.4.8.4)). C then have one method that overrides both because the signature matches both. (8.4.2)

However, one could wonder - just because two methods have the same name and parameter types, does not necessarily mean they have the same semantics. The name could very well be one english word that means two different things. What if we inherited two methods from two super interfaces that look the same but are actually different in semantics, therefore there should be two implementations in the subclass? For example

interface java.lang.Runnable
    void run()

interface com.animal.Runnable
    void run()

class Dog implements com.animal.Runnable,
                     java.lang.Runnable // a dog as a task
    ???

We can imagine a language that can handle such cases. But Java does not do that. If two methods are similar enough, they are assumed to have the same semantics. Fortunately in practice this does seems to be a problem anyway.

ZhongYu
  • 19,446
  • 5
  • 33
  • 61