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

Why can't Java find a suitable method when the input types are interfaces and the parameter types are implementing classes?

我有一个看起来像这样的 class 设置:

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

我真的很惊讶地发现这不能编译;它会抛出一个错误,指出它无法为类型 II 找到合适的方法 someMethod。我认为它会起作用,因为如果 IABC 的超级 class,它就会起作用。为什么 Java 不允许这样做?是否有任何解决方法,例如将 I 设为摘要 class?

此外,是否有此模式的名称以便我不必一直将其称为 "this"?

在编译时,方法是根据提供的参数的编译时类型(除其他事项外)选择的。

在这里,您的参数是 I 类型,但是您的 D class 没有提供任何具有两个 I 类型参数的 static 方法.

想象一下这个场景:

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

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

编译器无法知道或强制执行 I 只会由 ABC 实现。

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

接口的目的(粗略地说)是定义通用功能。如果所有实现者之间的功能不通用,则没有理由在那里有一个接口。

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

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

顾名思义,您可能正在尝试使用多重分派。