Reputation: 2766
I have a function which maps a class
object to an instance of this class.
Basically:
Function<Class<T>, T> fun;
I can define this function within a method but when trying to put this in a member variable, the compiler complains because the type T
is unknown.
So, T
is not specific to the enclosing object. It might differ from call to call. What is the correct syntax to define such a function on class level?
EDIT
I would like to clarify. I have class A
public class A {
public <T> T get(Class<T> clazz) {...}
}
Now, I want to hand a pointer to that function to class B
like this:
public class B {
<T> Function<Class<T>, T> fun;
public <T> T get(Class<T> clazz) {
return fun.apply(clazz);
}
}
However, the Syntax for <T> Function<Class<T>, T> fun
is incorrect. Is there a way to keep the information, that fun will always retain the type T
?
My current solution is
public class B {
Function<Class<?>, ?> fun;
public <T> void setFun(Function<Class<T>, T> fun) {
this.fun = fun;
}
public <T> T get(Class<T> clazz) {
return (T) fun.apply(clazz);
}
}
This works (and is obviously correct via invariant) but kinda ugly because of the required cast.
Upvotes: 4
Views: 1094
Reputation: 51683
In Java (and JVM) values are not polymorphic, methods are.
So correct is to define it with a method
<T> Function<Class<T>, T> fun();
Regarding EDIT.
Now, I want to hand a pointer to that function to class
B
like this:public class B { <T> Function<Class<T>, T> fun; public <T> T get(Class<T> clazz) { return fun.apply(clazz); } }
Once again, a value (including a field) can't be polymorphic, method can.
So you can make fun
a method
public abstract class B {
abstract <T> Function<Class<T>, T> fun();
public <T> T get(Class<T> clazz) {
return this.<T>fun().apply(clazz);
}
}
You can't write setter like setFun
. Its signature should be something like
public void setFun(<T> Function<Class<T>, T> fun); // pseudocode
rather than
public <T> void setFun(Function<Class<T>, T> fun);
<T> Function<Class<T>, T>
is called rank-N type and it's absent in Java
Alternatively, you can wrap polymorphic fun
with a class (interface)
public interface PolyFunction {
<T> T apply(Class<T> clazz);
}
public class B {
PolyFunction fun;
public void setFun(PolyFunction fun) {
this.fun = fun;
}
public <T> T get(Class<T> clazz) {
return fun.apply(clazz);
}
}
PolyFunction
looks like your A
so maybe you want
public class B {
A a;
public void setA(A a) {
this.a = a;
}
public <T> T get(Class<T> clazz) {
return a.get(clazz);
}
}
Upvotes: 2