当输入类型是接口且参数类型正在实现类时,为什么Java不能找到合适的方法?

时间:2015-02-02 19:46:37

标签: java class interface

我有一个类设置,看起来像这样:

interface I{}

class A implements I{}
class B implements I{}
class C implements I{}

class D{
    I a;
    I b;

    public D(I a, I b){
        this.a = a;
        this.b = b;
    }

    public void doSomething(){
        D.someMethod(a, b);
    }

    public static someMethod(A, A){//do something}
    public static someMethod(A, B){//do something}
    public static someMethod(A, C){//do something}
    public static someMethod(B, B){//do something}
    public static someMethod(B, C){//do something}
}

我很惊讶地发现这不会编译;如果找不到类型someMethodI的合适方法I,则会发出错误消息。我认为它会起作用,因为如果IABC的超类,那么它会起作用。为什么Java不允许这样做?是否有任何解决方法,例如将I作为抽象类?

此外,这个模式是否有名称,所以我不必继续将其称为"这"?

4 个答案:

答案 0 :(得分:4)

签名public static someMethod(A, A)可以接受A或更多派生类型的A。同样地,(A,B)等签名。

您需要一种接受(I,I)的方法,以便使用您在上面概述的任何类ABC来调用它。可替代性沿着继承链向下 - 您定义的形式参数必须是您希望具有的最不具体的类型,然后可以传入该类型的任何适当的继承者或实现者。

答案 1 :(得分:3)

在编译时,根据提供的参数的编译时类型(以及其他内容)选择方法。

此处,您的参数属于I类型,但您的D类未提供任何static个方法,其中包含两个I类型的参数。

答案 2 :(得分:2)

想象一下这种情况:

new D( new I() {}, new I() {} ).doSomething();

这是完全合法的,但参数肯定不适合您提供的任何实现。

编译器无法知道或强制I仅由ABC实施。

如果您发现自己处于这种状况,那通常表明设计不佳。解决方案是编写接口I,使其与实现它的方法无关。

接口的目的(粗略地说)是定义通用功能。如果所有实施者之间的功能并不常见,则没有理由在那里设置接口。

答案 3 :(得分:1)

就名称而言,看起来您可能尝试使用多次发送。