Consider the following example:
public interface Greeter {
String greet();
}
public class ExplicitGreeterImpl implements Greeter {
@Override
public String greet() {
return "Hello World!";
}
}
public class ImplicitGreeterImpl {
public String doTheGreeting() {
return "Hello World!";
}
}
private void run() {
System.out.println(new ExplicitGreeterImpl().greet());
Greeter foo = new ImplicitGreeterImpl()::doTheGreeting;
System.out.println(foo.greet());
}
The functional interface Greeter
has two implementations. ExplicitGreeterImpl
implements Greeter
using the implements
clause, while ImplicitGreeterImpl::doTheGreeting
implements Greeter
without it. Nevertheless, ImplicitGreeterImpl::doTheGreeting
is designed to implement Greeter
, just like ExplicitGreeterImpl
.
Now, I want to refactor the Greeter
interface, so I can pass a name to it:
public interface Greeter {
String greet(String name);
}
I can do this with the Change Method Signature refactoring provided by Eclipse (I am sure other IDEs have a similar refactoring). This automatically updates all implementations and usages of the Greeter
interface. Implementations receive the new parameter, while usages pass a configurable default value. This works fine for the ExplicitGreeterImpl
, however the refactoring does not touch the ImplicitGreeterImpl::doTheGreeting
method. Thus, the assignment
Greeter foo = new ImplicitGreeterImpl()::doTheGreeting;
becomes a compile-time error. To fix this, I have to manually adjust the signature of the method ImplicitGreeterImpl::doTheGreeting
.
Now, I understand that it is undesirable in many cases to automatically adjust the signature of ImplicitGreeterImpl::doTheGreeting
. However, I feel that the current workflow can be improved:
For example, ImplicitGreeterImpl
could look like this:
public class ImplicitGreeterImpl {
@Implements(Greeter.class)
public String doTheGreeting() {
return "Hello World!";
}
}
Now, refactoring tools could be sure that ImplicitGreeterImpl::doTheGreeting
is supposed to implement Greeter
and thus, they can automatically change its signature.
Thus, my question is: Is there a way to tell refactoring tools that a given method is supposed to implement a given functional interface? I searched for the annotation proposed above, but I did not find anything useful.
I kept searching for an answer, but there does not seem to be a solution that uses an annotation. However, when asking the question I had a specific use case in mind: I want to write down many different implementations of the same functional interface in a single file. Indeed, there is a solution for this problem, which also works great with automatic refactoring tools:
public interface Greeter {
String greet();
}
public enum EnumGreeterImpl implements Greeter {
GREETER1 {
@Override
public String greet() {
return "Hello World!";
}
},
GREETER2 {
@Override
public String greet() {
return "Foo bar";
}
},
}
private void run() {
Greeter foo = EnumGreeterImpl.GREETER1;
System.out.println(foo.greet());
}
See also: