Reputation: 243
I am trying to make a somewhat strong typed API:
class PropertyType<T> { ... }
class SubType1<T> extends PropertyType<T> { ... }
class SubType2<T> extends PropertyType<T> { ... }
class PropertyHandler<K extends PropertyType<?>> {
// Here, the V generics is not related to the property type,
// hence the value is not typed
public <V> getValue(K prop) { ... }
// In this case, we have correct typing, but T is not bounded to K
public <V, T extends PropertyType<V>> getValue(T prop) { ... }
// This would be a solution, but it doesn't compile because K is a type variable
public <V, T extends K & PropertyType<V>> getValue(T prop) { ... }
}
And that is how it would be used:
PropertyHandler<SubType1<?>> ph = new PropertyHandler<>();
// I want to allow this
SubType1<Integer> p1 = new SubType1<>();
SubType1<Boolean> p2 = new SubType1<>();
Integer v1 = ph.getValue(p1);
Boolean v2 = ph.getValue(p2);
// I don't want to allow this
SubType2<Integer> p3 = new SubType2<>();
Boolean v3 = ph.getValue(p3);
Is there a way to solve this ? Maybe it's some architecture problem that can be handled differently ?
Upvotes: 2
Views: 86
Reputation: 1491
The return type for getValue()
must be added to the generic signature of PropertyHandler
. Otherwise, there is no way for PropertyHandler
to infer the getValue()
return type from the generic definition of PropertyType
.
Therefore, either assign both return type and property type to the PropertyHandler
generic signature, or flip it by specifying the return type in PropertyHandler
, and having PropertyHandler
ensure the correct PropertyType
parameter type, like this:
class PropertyType<T, H extends PropertyHandler<T>> {
public T getValue() { ... }
}
class IntegerType extends PropertyType<Integer, PropertyHandler<Integer>> { ... }
class BooleanType extends PropertyType<Boolean, PropertyHandler<Boolean>> { ... }
class PropertyHandler<V> {
public <T extends PropertyType<V, PropertyHandler<V>>> V getValue(T prop) {
return prop.getValue();
}
}
This is how you would use it:
PropertyHandler<Integer> ph = new PropertyHandler<>();
IntegerType p1 = new IntegerType();
Integer v1 = ph.getValue(p1); // works fine
BooleanType p3 = new BooleanType();
Boolean v3 = ph.getValue(p3); // compile time error
Upvotes: 1