Chris Welsh
Chris Welsh

Reputation: 349

Java interface inheritance causes IDE confusion

I have interfaces extending other interfaces. When the implementations of those interfaces are used, my IDE (Eclipse and IntelliJ idea) is unable to resolve the implementing class. This does not prevent the code from compiling, but it's very peculiar that the IDE is so uncertain. Is there something fundamental I am misunderstanding? I present a simplified structure that outlines the problem.

A base interface

public interface Avoidable {

    public void avoid();

}

An interface that extends the base one

public interface MostlyAvoidable extends Avoidable {

    public void most();

}

It's implementation

public class MostlyAvoidableImpl implements MostlyAvoidable {
    @Override
    public void most() {}

    @Override
    public void avoid() {}
}

A second extending interface

public interface SomewhatAvoidable extends Avoidable {

    public void somewhat();

}

And its implementation

public class SomewhatAvoidableImpl implements SomewhatAvoidable {

    @Override
    public void avoid() {}

    @Override
    public void somewhat() {}

}

Finally a class that uses one of these implementations:

public class UsesSomewhatAvoidable {

    private SomewhatAvoidable somewhatAvoidable;

    public UsesSomewhatAvoidable(SomewhatAvoidable somewhatAvoidable) {
        this.somewhatAvoidable = somewhatAvoidable;
    }

    public void someMethod() {
        somewhatAvoidable.avoid();
    }
}

Now, if I navigate to the somewhatAvoidable.avoid(); line and ask the IDE to find the code that implements the avoid() method, it asks me if I mean MostlyAvoidableImpl or SomewhatAvoidableImpl. Why? Surely it can figure this out?

This is what happens in Idea 10.5 when pressing Ctrl+Alt+B (admittedly quite an old version now), but it also happens in the latest version of Eclipse.

Idea 10.5 behaviour

Edit: corrected typo in last line - SimplyAvoidImpl to SomewhatAvoidableImpl, and added screenshot.

Upvotes: 0

Views: 196

Answers (3)

Code-Apprentice
Code-Apprentice

Reputation: 83527

From the code you have given, somewhatAvoidable (in the UsesSomewhatAvoidable class) is declared as a SomewhatAvoidable which is an interface and doesn't have an implementation for the avoid() method. The compiler (and thus the IDE) cannot know which class you want to jump to for the implementation.

Upvotes: 0

maba
maba

Reputation: 48045

I took all your interfaces and classes and set it up in my own IntelliJ and I don't have the problem you describe.

Position the caret at the avoid method in UsesSomewhatAvoidable and then press Ctrl+Alt+B (Go To | Implementation(s)):

enter image description here

And I end up at the implementation in SomewhatAvoidableImpl:

enter image description here

Upvotes: 3

Michael Berry
Michael Berry

Reputation: 72274

Surely it can figure this out?

Yes, it should be able to figure out that the avoid() method executes using the interface given by SomewhatAvoidable. If it's giving a completely different class (such as MostlyAvoidableImpl in this case) then as far as I can see that would be a bug (with the example you've given anyway, I can't see how SomewhatAvoidable could possibly relate to MostlyAvoidableImpl.) It's possible you've confused the IDE somehow - try cleaning or restarting and see if it makes a difference.

However, it may validly give you an option to select an implementation more specifically, since this cannot be determined by static analysis (but obviously one such implementation has to be selected for the program to work correctly at runtime.)

Upvotes: 1

Related Questions