简体   繁体   English

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

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

I have a class setup that looks something like this: 我有一个看起来像这样的类设置:

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

I was really surprised to find out this doesn't compile; 我真的很惊讶地发现它无法编译。 it'll throw an error saying it can't find a suitable method someMethod for types I and I . 它会抛出错误,指出无法为II类型找到合适的方法someMethod I thought it would work because if I were a superclass of A , B and C it would work. 我认为它会起作用,因为如果IABC的超类,那它将起作用。 Why doesn't Java allow for this? Java为什么不允许这样做? Is there any workaround, like making I an abstract class? 有没有解决方法,例如使I成为抽象类?

Also, is there a name for this pattern so I don't have to keep referring to it as "this"? 另外,该模式是否有名称,所以我不必一直将其称为“此”?

The signature public static someMethod(A, A) can accept A or more-derived types of A . 签名public static someMethod(A, A)可以接受A或更多派生的A类型。 Similarly the (A,B) and so forth signatures. 类似地, (A,B)等签名。

You would need a method that accepts (I,I) in order to call it with any of the classes A , B , C that you sketched out above. 您将需要一个接受(I,I)的方法,以便使用您在上面勾勒出的类ABC进行调用。 Substitutability goes down the inheritance chain - the formal parameter you define must be the least-specific type you wish to have in common, and then any proper inheritor or implementor of that type can be passed in. 可替换性沿继承链延伸-您定义的形式参数必须是您希望共有的最不特定的类型,然后可以传入该类型的任何适当的继承者或实现者。

At compile time, methods are chosen based on the compile-time types of the arguments provided (among other things). 在编译时,将根据所提供参数的编译时类型(以及其他方法)来选择方法。

Here, your arguments are of type I , but your D class does not provide any static methods with two parameters of type I . 在这里,您的参数的类型为I ,但是您的D类没有提供带有两个类型为I参数的static方法。

Imagine this scenario: 想象一下这种情况:

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

This is perfectly legal, yet the parameters definitely won't fit any of the implementations you provided. 这是完全合法的,但是这些参数绝对不适合您提供的任何实现。

The compiler has no way to know or enforce that I will only ever be implemented by A , B or C . 编译器无法知道或强制I只能由ABC

If you find yourself in this situation, that's usually an indicator of poor design. 如果您发现自己处于这种情况,则通常表明设计不佳。 The solution is to write the interface I in a way that it won't matter for the methods that work with it who implements it. 解决方案是以一种对接口I无关的方式编写接口I ,该接口I与实现该接口的方法无关。

The purpose of an interface (roughly speaking) is to define common functionality. 接口的目的(大致而言)是定义通用功能。 If the functionality isn't common between all implementers, there is no reason to have an interface there. 如果该功能并非在所有实现者之间都通用,则没有理由在那里建立接口。

顾名思义,您似乎正在尝试使用多个调度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM