Reputation: 33
I want to store a function to be applied to any instance of a class. As I want to do this for different classes, I am using an interface in my storing and applying code. But I have some problems with my type variables:
I've got an interface
public interface SomeInterface<P>
And an implementing class
public class SomeClass implements SomeInterface<Object>
As well as a handler
public class SomeHandler {
public <R> void someMethod(Function<SomeInterface<R>,R> someFunction) {}
}
And the code
public void someTest() {
Function<SomeClass,Object> someFunction = a -> new Object();
SomeHandler handler = new SomeHandler();
handler.someMethod(someFunction); //error here
}
will not work.
The error at the marked location is "No Instance(s) of type variable(s) R exist so that SomeClass conforms to SomeInterface"
I already tried to use an abstract class instead of the interface. This did not work either.
I did some research and found a bug including lambda-expressions. Removing the lambda expression did not solve the issue. Another page hints to a bug in OpenJdk recommending to change the order of the type variables. As I am using the java Function class, I am not able to do this.
I also tried to get the Oracle Jdk, but I am not allowed to do anything on this machine.
Any thought is welcomed!
Upvotes: 1
Views: 97
Reputation: 140318
Function<SomeClass,Object> someFunction = a -> new Object();
isn't an instance of Function<SomeInterface<R>,R>
.
You can either do what Georg Henkel suggests: to change the type of the someFunction
variable; or you could just inline the lambda in the method call, and hide the type declaration:
handler.someMethod(a -> new Object());
Or, to keep your existing type at the call site, change the method signature to:
public <R, S extends SomeInterface<R>>
void someMethod(Function<S, R> someFunction)
but note that in order to be able to call someFunction.apply
with anything other than literal null
, you will have to pass in a S
(or something containing a S
, like a Collection
or an Optional
) as an additional method parameter.
If you don't need to call someFunction.apply
(the question is then why you'd need it...), you can drop the S
type variable, and just use:
public <R> void someMethod(Function<? extends SomeInterface<R>, R> someFunction)
Upvotes: 1
Reputation: 3605
Change the Function in someTest()
to:
Function<SomeInterface<Object>, Object> someFunction = a -> new Object();
UPDATE depending on your comment:
You could generalise your handler method to something more of that kind:
public <R> void someMethod(Function<? extends SomeInterface<R>, R> someFunction) {}
This allows you to use something like the following as Function:
Function<SomeOtherClass, MyObject> someFunction = a -> new MyObject();
Upvotes: 0