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?
You can't inherit any functional interface to another functional interface. Because it breaks the law of functional interface has exactly one abstract method.
A functional interface can extends another interface only when it does not have any abstract method.
In Java 8, there are 4 main functional interfaces are introduced which could be used in different scenarios.
Functional interfaces are interfaces that ensure that they include precisely only one abstract method. Functional interfaces are used and executed by representing the interface with an annotation called @FunctionalInterface. As described earlier, functional interfaces can contain only one abstract method.
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With