简体   繁体   中英

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 . I thought it would work because if I were a superclass of A , B and C it would work. Why doesn't Java allow for this? Is there any workaround, like making I an abstract class?

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 . Similarly the (A,B) and so forth signatures.

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

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 .

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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