Kristoffer
Kristoffer

Reputation: 251

Replacing abstract base class with interface in IntelliJ

I have an abstract base class with a single abstract method that I would like to get rid of. I would like to introduce a new interface with that method and make all existing subclasses to implement that interface rather than extending the base class.

From:

public abstract class Base {
  public abstract Foo getFoo();
}

public class Concrete extends Base {
  public Foo getFoo() {
    throw new UnsupportedOperationException();
  }
}

To:

public interface Base {
  Foo getFoo();
}

public class Concrete implements Base {
  public Foo getFoo() {
    throw new UnsupportedOperationException();
  }
}

I have tried to inline the baseclass without success, created the interface manually, pulling member and then delete the then empty base class, but I can't seem to get IntelliJ to complete this operation automatically.

Any suggestions on how I can solve this?

Upvotes: 5

Views: 3655

Answers (2)

Bas Leijdekkers
Bas Leijdekkers

Reputation: 26482

Type Alt+Enter on the name of the superclass and invoke Convert class to interface.

This quick fix is provided by the "Abstract class may be interface" inspection which is enabled by default in "No highlighting, only fix" mode. But if you have disabled it, you will need to enable it again

Upvotes: 1

Kristoffer
Kristoffer

Reputation: 251

I realise now that I managed to fool myself into thinking this was an IDEA problem. Rather it is related to the abstract type I tried to inline being used in quite a few generics references, i.e.

final MyMapping<Base, String>  = (...)

IDEA cannot guess what I would like to do with all these generic references. These must be resolved manually and apart from that the following does work. I start off with:

public abstract class AbstractSomething {
    public abstract void foo();
}

public class ConcreteSomething extends AbstractSomething {
    @Override
    public void foo() {
        throw new UnsupportedOperationException();
    }
}

Then I add:

public abstract class AbstractSomething implements Something {..}

and alt-enter on Something choosing to add that interface. I then refactor->pull members up and confirm to move the abstract method to the Something interface, the result being:

public interface Something {
    void foo();
}
public abstract class AbstractSomething implements Something {
}

With the cursor blinking on AbstractSomething in ConcreteSomething, ctrl+alt+n to inline superclass. AbstractSomething is a goner and I am left with

public class ConcreteSomething implements Something {
    @Override
    public void foo() {
        throw new UnsupportedOperationException();
    }
}

You just gotta love this IDE, it is always smarter than I am.

Upvotes: 2

Related Questions