1

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!

2 Answers 2

1
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)
1
  • Thank you! I am skipping the declaration now. As a work around, I used Function someFunction = a -> new Object(); and had no warning or anything. But I think, skipping the declaration is "nicer".
    – Agast
    Commented Jan 19, 2018 at 15:26
0

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();
3
  • Yes, this works! However, this means that all my dispatchers are working with SomeInterface<Object> instead of the different Classes. So this is my last resort.
    – Agast
    Commented Jan 19, 2018 at 10:04
  • The disadvantage of changing someFunction to use extends is that you then can't pass anything to it, other than null. Commented Jan 19, 2018 at 10:19
  • Thank you for your suggestion and the time you invested! I am skipping the declaration now as Andy recommends.
    – Agast
    Commented Jan 19, 2018 at 15:27

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.