Java是否支持像C#一样的显式接口实现?

4
我尝试做了这个:
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();
    }    
}

尽管我可以将roboGarfeild对象转换为其petrobot类型,但我不能像C#那样进行显式实现

我做错了什么吗?还是Java不支持这个功能?

编辑:因此,Java不支持像C#那样的显式接口实现。但对于无法避免的情况,Holger的委托方法似乎是解决之道。

感谢所有回复。


你必须确保同一个对象的同一个方法不会执行两个不同的操作。我不确定为什么你想要这样一个令人困惑的边缘情况。 - Peter Lawrey
@PeterLawrey:只是为了学习目的。我比较熟悉Java而不是C#,当我看到C#允许的这个东西时,我用Java测试了一下。就这样。 - Somjit
@SomjitNag 是的。Java移除/修改了一些功能,以消除这种模棱两可的行为。 - Suresh Atta
也许他们可以保留一个警告或者类似的东西,告诉我们何时出现这样的方法... - Somjit
我认为警告并不能帮助,因为不应该有任何困惑的必要。仍然只能有一个实现。 - Peter Lawrey
人类的眼睛不是编译器的眼睛 :) - Suresh Atta
3个回答

4
这类问题的标准解决方案是使用委托:
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();
    }    
}

对于较大的方法,建议让内部类委托给外部类以保持内部类的简短。此外,子类可以重写这些方法而不必处理委托问题。

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();
    }    
}

你能解释一下 public String toString() { return roboGarfield.this.toString(); }; 的必要性吗?我不确定我是否正确理解了它。 - Somjit
2
没有必要。只是在调试或其他需要以文本形式打印对象以查看roboGarfield实例的字符串表示(如果您希望拥有复杂的toString实现)而不是继承自java.lang.Object的内部类实例的表示时,它会有所帮助。在这个小例子中,它没有任何影响,因为它没有被使用。但我添加了它们作为提示,因为您很可能希望在实际代码中使用它们。 - Holger
如果您不理解语法:这意味着内部类的 toString 方法委托给外部类的 toString 方法。因此,t.asPet().toString()t.asRobot().toString() 都返回与 t.toString() 相同的结果。 - Holger
非常感谢您提供具有未来可扩展性的答案 :) 我理解了语法,但是对于特定代码它所执行的操作我无法联系起来。 - Somjit

3

Java不会这样做。

如果两个接口定义了相同签名(signature)的方法,没有办法区分它们,你只能提供一个实现来同时满足两个接口。

你需要注意避免出现这种不兼容的接口。


霍尔格的方法怎么样?当你必须要回退时,那看起来像是一个备选方案... - Somjit
1
是的,那样做可以。但需要一些工作。而且你不再拥有一个实现两个接口的单个对象实例。 - Thilo
没错,但我觉得知道有备份也是好事。 - Somjit
我不认为那是一个备份。匿名内部类并不是使用接口进行编程。:) - 我想回应@Thilo关于这个问题。这样我的假设就会变得清晰明了。 - Suresh Atta
@Thilo:“而且你不再有一个实现两个接口的单个对象实例”——你仍然有可能将适当的对象传递到任何需要实现任一接口的地方。在需要在单个对象中实现两个接口的地方(这在Java中相当罕见),无论如何都无法使用不同的行为来实现它们。 - Holger

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.
     }

当你这样做时,在Java中,单一实现适用于两个接口。据我所知,没有解决方法。

3
+1 表示澄清,只有一种实现方式,因此强制类型转换不起作用。 - Peter Lawrey
1
所以,我加了一点描述。看看Perter的意思。希望有所帮助。 - Suresh Atta
所以,如果我理解正确-由于我无法“明确”sleep()方法,强制转换不会添加任何内容,两者将给出相同的结果,因为它们都被覆盖为相同的单一代码。这是什么意思,对吧? - Somjit
@SomjitNag 您说得很对。强制转换没有任何影响。 - Suresh Atta
Holger的解决方案看起来不错,有人对此有意见吗? - Somjit
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接