4

i tried doing this :

interface pet {
    void sleep();
}
interface robot {
    void sleep();
}

public class roboGarfield implements pet , robot {

    /*
     * this gives error
    void pet.sleep(){

    }
    */

    @Override
    public void sleep() { System.out.println("this isn't really specific.."); }

    public static void main(String[] args){
        roboGarfield t = new roboGarfield();
        t.sleep();
        ((pet)t).sleep(); // similar to C# 
        ((robot)t).sleep();
    }    
}

But even though i can cast the roboGarfeild object to its pet or robot type , i cant do an explicit implementation like c#.

Anything i'm doing wrong ? or is it just not supported in java ?

Edit: So , java doesn't support explicit interface implementation like C#. But for cases where they can't be avoided , Holger's delegate method seems like the way out.

Thanks for all the replies.

Somjit
  • 2,503
  • 5
  • 33
  • 60
  • You have to ensure that the same method doesn't do two different things for the same object. I am not sure why you would want such a confusing edge case. – Peter Lawrey Oct 01 '13 at 08:13
  • @PeterLawrey : just for learning purposes. I'm more familiar with Java than c# , and when i saw this thing that C# allowed , i tested it out with java. that's all. – Somjit Oct 01 '13 at 08:18
  • @SomjitNag Yes. java removed/modified some features to get rid off these type of Ambiguous behavior. – Suresh Atta Oct 01 '13 at 08:20
  • maybe they could have kept a warning or something that tells us when such methods pop up ... – Somjit Oct 01 '13 at 08:33
  • I don't think a warning would help because there shouldn't be any need to be confused. There can still only be one implementation. – Peter Lawrey Oct 01 '13 at 08:38
  • A human eye is not a compiler eye :) – Suresh Atta Oct 01 '13 at 08:49

3 Answers3

4

The standard solution to this kind of problem is to use delegation:

interface pet {
    void sleep();
}
interface robot {
    void sleep();
}

public class roboGarfield {

    private final pet myPetIdentity = new pet() {
      public void sleep() { System.out.println("sleeping as pet"); }
      public String toString() { return roboGarfield.this.toString(); };
    };
    private final robot myRobotIdentity = new robot() {
      public void sleep() { System.out.println("recharging as robot"); }
      public String toString() { return roboGarfield.this.toString(); };
    };

    public final pet asPet() {
      return myPetIdentity;
    }
    public final robot asRobot() {
      return myRobotIdentity;
    }
    public static void main(String[] args){
        roboGarfield t = new roboGarfield();
        t.asPet().sleep(); 
        t.asRobot().sleep();
    }    
}

For bigger methods it’s recommended to let the inner classes delegate back to the outer class to keep the inner classes short. Further, subclasses could override these methods without dealing with the delegation stuff then.

public class roboGarfield {

    private final pet myPetIdentity = new pet() {
      public void sleep() { petSleep(); }
      public String toString() { return roboGarfield.this.toString(); };
    };
    private final robot myRobotIdentity = new robot() {
      public void sleep() { roboSleep(); }
      public String toString() { return roboGarfield.this.toString(); };
    };

    public void roboSleep()
    {
      System.out.println("recharging as robot");
    }
    public void petSleep()
    {
      System.out.println("sleeping as pet");
    }
    public final pet asPet() {
      return myPetIdentity;
    }
    public final robot asRobot() {
      return myRobotIdentity;
    }
    public static void main(String[] args){
        roboGarfield t = new roboGarfield();
        t.asPet().sleep(); 
        t.asRobot().sleep();
    }    
}
Holger
  • 285,553
  • 42
  • 434
  • 765
  • can you explain the need for `public String toString() { return roboGarfield.this.toString(); };` . I'm not sure i understand that properly. – Somjit Oct 01 '13 at 08:53
  • 2
    There’s no need for it. It just helps in case of debugging or other activities where objects are printed in textual form to see the string representation of the `roboGarfield` instance (where you might have a sophisticated `toString` implementation, if you wish) instead of the representation of the inner class instance inherited by `java.lang.Object`. In this small example here it has no effect as it is not used. But I added them as a hint as you most likely want to have them in real life code. – Holger Oct 01 '13 at 10:40
  • If you don’t understand the syntax: it means the inner class `toString` method delegates to the outer class’ `toString` method. So `t.asPet().toString()` and `t.asRobot().toString()` both return the same result as `t.toString()` – Holger Oct 01 '13 at 10:45
  • thanks a lot for the future-proof answer :) i understood the syntax , but i couldn't connect the dots as to what it was doing for the particular code. – Somjit Oct 01 '13 at 14:43
3

Java does not do that.

If two interfaces define methods of identical signature, there is no way to distinguish between them and you can only provide a single implementation that will be used by both.

You have to take care not to end up with interfaces that are incompatible that way.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • what about Holger's method ? that looks like something to fallback to when you must... – Somjit Oct 01 '13 at 08:41
  • 1
    Yes, that would work. But it is some work. And you no longer have a single object instance that implements both interfaces. – Thilo Oct 01 '13 at 08:43
  • True , but i guess its good to know that there is some backup . – Somjit Oct 01 '13 at 08:44
  • I don't think that is a backup. `Anonymous inner classes` are not programming with interface. :) –,I would like to respond @Thilo on this. So that my assumptions gets clear. – Suresh Atta Oct 01 '13 at 08:47
  • @Thilo: “And you no longer have a single object instance that implements both interfaces”— You still have a possibility to pass an appropriate object to any place where an implementation of either interface is required. And at places where *both* interfaces are required to be implemented in a single object (that’s rather rare in Java) there’s no way of implementing them with different behavior anyway. – Holger Oct 01 '13 at 10:53
1
public class roboGarfield implements pet , robot {

     @ovveride
     public void  sleep(){
         //here you are implementing sleep method
         //But satisfying both pet and robot interface's sleep method.
     }

When you do this , in java the single implementation works for the both interface. AFAIK, NO work around.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
  • 3
    +1 to clarify, there is only one implementation so casting has no effect. – Peter Lawrey Oct 01 '13 at 08:12
  • @PeterLawrey : i didn't get you when you said "one implementation" . If possible , can you explain that part a little ? – Somjit Oct 01 '13 at 08:23
  • 1
    Somit ,I edited with little description. See what Perter means. Hope it helps – Suresh Atta Oct 01 '13 at 08:26
  • thanks :) So , if i'm getting it correctly - Since i cant "explicify" the sleep() methods , casting doesn't add anything , both will give the same result , as both are over-riden to the same single code. this is what it means right ? – Somjit Oct 01 '13 at 08:31
  • @SomjitNag You got it exactly. There is no effect of casting. – Suresh Atta Oct 01 '13 at 08:32
  • Holger's solution looks good , anybody have an opinion on that ? – Somjit Oct 01 '13 at 08:42
  • That works. Those called as `Anonymous inner classes` and not programming with interface. :) – Suresh Atta Oct 01 '13 at 08:45
  • @ sᴜʀᴇsʜ ᴀᴛᴛᴀ: “programming with interface” is still “programming with interface” when you let anonymous inner classes implement an interface. – Holger Oct 01 '13 at 10:50
  • @Holger That is OK, But the I don't think they satisfy the key OOP aspect `Ploymorphism`, *IMHO*. – Suresh Atta Oct 01 '13 at 10:53
  • @ sᴜʀᴇsʜ ᴀᴛᴛᴀ: Why not? There is exactly the same amount of polymorphism regardless of whether the inner class or the outer class implements an interface. – Holger Oct 01 '13 at 10:57
  • This answer does not provide any additional information to simply stating "No, Java does not support explicit interface implementation". it just confuses the matter with stating that instance of this class can be assigned to an interface variable. This is description of implicit interface implementation in the terms of .NET. Which is not the question asked. – Dennis Aug 11 '14 at 20:12