Let's say I have two classes
class A{
int a;
int getA(){
return this.a;
}
}
and
class B extends A{
String b;
String getB(){
return this.b;
}
}
I would like to have an enum, containing all possible values and and getters of inheritance tree (don't ask, I just want to).
enum ValueGetters{
A("a", A::getA),
B("b", B::getB);
String parameterName;
Function parameterGetter;
}
I have problem writing constructor for this class.
ValueGetters(String parameterName, Function parameterGetter){
this.parameterName = parameterName;
this.parameterGetter = parameterGetter;
}
returns error for both A and B (Error:(12, 14) java: incompatible types: invalid method reference
).
The same situation is for ValueGetters(String parameterName, Function<?,?> parameterGetter)
For ValueGetters(String parameterName, Function<? extends A,?> parameterGetter)
this gives error only for B, and if I try to overload constructor with ValueGetters(String parameterName, Function<? extends B,?> parameterGetter)
I have new error that both types have the same type of erasure.
On the other hand ValueGetters(String parameterName, Object parameterGetter)
returns error stating that Object
is not a Function
.
I have tried to define my own @FunctionalInterface
but it gave me the same error, and overloading methods of @FunctionalInterface
to accept both A
and B
apparently is not an option (or not an obvious one).
If anyone could propose solution to my problem I would greatly appreciate it.
EDIT & SOLUTION
I know it's not exactly an enum, but it works in the same way and provides functionality I needed:
- Returns getter
- Getter is type-sensitive
- Solution does not require any changes in the original class
- Works well with interfaces
...and now, the code:
public class ValueGetter<T extends A, R> {
private String name;
private Function<A,R> getter;
private ValueGetter(String name, Function<A, R> getter){
this.name = name;
this.getter = getter;
}
private static <T extends A, R> ValueGetter create(String name, Function<T,R> valueGetter){
return new ValueGetter(name, valueGetter);
}
public static ValueGetter<A, Integer> AA = create("a", A::getA);
public static ValueGetter<B, Integer> BB = create("a", B::getB);
public Function<T, R> getGetter(){
return (Function<T, R>) this.getter;
}
}
With this implementation
A a1 = new A(12345);
B b1 = new B(54321, "sdfghjk");
System.out.println(ValueGetter.AA.getGetter().apply(a1));
System.out.println(ValueGetter.AA.getGetter().apply(b1));
System.out.println(ValueGetter.BB.getGetter().apply(b1));
compiles and works, while line
System.out.println(ValueGetter.BB.getGetter().apply(a1));
gives compilation error apply(B) in function cannot be applied to (A)