Java中关于接口的查询

9
假设我有两个接口,分别为接口 A 和接口 B:
public interface A {
  public int data();
}

public interface B {
  public char data();
}

接口A有一个方法public int data(),接口B有一个方法public char data()

当我在某个类C中实现了接口A和接口B时,编译器会报错。这是Java的一个缺陷吗?我认为这是我们不允许继承多个类的主要原因之一,那么既然这个问题仍然存在,为什么我们还允许实现多个接口呢?


1
请问您能否发布错误信息? - higuaro
4个回答

7

Java教程:定义方法-重载方法中指出:

Java编程语言支持方法重载,Java可以区分具有不同方法签名的方法。这意味着,如果类中的方法具有不同的参数列表,则它们可以具有相同的名称。

此外,

您不能声明具有相同名称和相同数量和类型参数的多个方法,因为编译器无法区分它们。

编译器在区分方法时不考虑返回类型,因此即使它们具有不同的返回类型,您也不能声明具有相同签名的两个方法。

这两个实现的方法共享一个常见的方法签名(即data()),因此编译器无法区分两者,并将该单个方法满足两个接口合同。


编辑:

例如,

public class Foo implements IFoo, IBar{

    public static void main(String[] args) {
        Foo foo = new Foo();
        ((IFoo) foo).print();
        ((IBar) foo).print();
    }

    @Override
    public void print() {
        System.out.println("Hello, World!");
    }
}

public interface IBar {
    void print();
}

public interface IFoo {
    void print();
}

这将输出:

Hello, World! 
Hello, World!

那么Java如何处理在多个接口中具有相同签名和返回类型的方法呢? - chaosguru
1
我认为它会成功编译 :) - chaosguru
1
如果签名、名称和返回类型相同,则无需进行任何操作,实现了两个接口。两个接口均已实现。 - Francisco Spaeth
@Spaeth:是的,没错。但对于上面的问题来说,这意味着他正在尝试多重继承? - chaosguru
不,使用两个接口意味着您的类实现了两个契约,它没有继承...多重继承是当您扩展了超过一个时(但是那时您将有其他类型的问题,请查看我的答案;))。 - Francisco Spaeth

4
Java编译器(我认为C#也是一样)不会根据返回值来区分方法。在您的情况下,尽管返回类型不同,编译器仍将这两种方法视为相同。

2
你提出的问题与多重继承无关,实现多个接口的类也不是问题。
当你定义一个接口时,你只是在说这个接口的实现者应该遵守一个协议,并实现该接口中定义的所有方法。
一个类的实现可以实现多个接口而不会出现问题,但是接口不能冲突。在你的情况下,你试图实现两个声明了相同签名的接口方法
在Java中,方法签名由名称和参数类型组成。

定义:方法声明的两个组成部分构成了方法签名——方法的名称和参数类型。

http://docs.oracle.com/javase/tutorial/java/javaOO/methods.html

为了重载一个方法,你需要拥有不同的签名。
在Java中,多继承是不被允许的,因为会出现复杂的问题,比如当一个方法由两个或更多个父类实现时该如何定义其实现。对于这个话题,我建议看一下钻石问题
事实上,在某些情况下,接口被用来模拟多重继承,允许类呈现出合并的方法集。

0
一种解决方案是使用内部类:
  1. 你的 "C 类" 实现了接口 "A"

  2. 你还有一个内部类 "D",它实现了接口 "C":

    public class C implements A { ... private class D implements B {

如果你确实需要在同一个类中同时使用这两个接口,这可能让你既能拥有蛋糕,又能吃掉它 :)


你的意思是内部类 D 实现了接口 B 吗? - chaosguru

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