Reputation: 50716
I have a custom interface I've been using for some time that looks something like this:
public interface Function<T, R> {
R call(T input);
}
I'd like to retrofit this interface with both Java's Function
as well as Guava's Function
, while keeping it a FunctionalInterface
. I thought I had the perfect arrangement:
@FunctionalInterface
public interface Function<T, R> extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
R call(T input);
@Override
default R apply(T input) {
return call(input);
}
}
Both superinterfaces declare the same apply()
method, which has been implemented in my interface, leaving only the abstract call()
method. Strangely, it won't compile, telling me
Invalid '@FunctionalInterface' annotation; Function<T,R> is not a functional interface
Stranger still, the following variations compile just fine:
@FunctionalInterface
public interface Function<T, R> extends
java.util.function.Function<T, R> {
R call(T input);
@Override
default R apply(T input) {
return call(input);
}
}
@FunctionalInterface
public interface Function<T, R> extends
com.google.common.base.Function<T, R> {
R call(T input);
@Override
default R apply(T input) {
return call(input);
}
}
public interface Function<T, R> extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
R call(T input);
@Override
default R apply(T input) {
return call(input);
}
}
@FunctionalInterface
public interface Function<T, R> extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
@Override
R apply(T input);
}
Is there a reason the first version won't compile?
Upvotes: 20
Views: 7158
Reputation: 29520
As stated in the comments, it compiles fine with the oracle compiler. It is an eclipse bug.
Awaiting for a bug fix, personally i will remove the annotation @FunctionalInterface
(your 3rd variation):
public interface Function<T, R>
extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
R call(T input);
@Override
default R apply(T input) {
return call(input);
}
}
The major inconvenient of this solution is that the eclipse compiler bug prevent from using the Function
as a lambda target type.
If you really want to keep @FunctionalInterface
on your Function
, a (ugly) workaround might be to introduce an intermediate interface:
public interface AdapterFunction<T, R>
extends
java.util.function.Function<T, R>,
com.google.common.base.Function<T, R> {
@Override
default R apply(T input) {
return null;
}
}
and let your Function
extends this AdapterFunction
:
@FunctionalInterface
public interface Function<T, R>
extends
AdapterFunction<T, R> {
R call(T input);
@Override
default R apply(T input) {
return call(input);
}
}
In this case, the Function
is a valid target type for eclipse too:
Function<String, Object> function = st -> st.toString();
Upvotes: 10