Reputation: 2121
I have a class who relies on generics to bind types internally.
class C<T1, T2 extends T1> {
T1 e1;
T2 e2;
/* stuff */
}
In my code I know that, while c.e1
and c.e2
might not have the same class, c.e2
is an instance of a subclass of the class of c.e1
.
I need to create a List
of these c
s, and those elements would not share a common base class. Still, I want to preserve the fact that each element of the List
has the attributes bounded between each other.
Ideally I would like to create a List<C<?, ? extends ...>>
"but" I don't know any syntax to specify this behaviour.
And using a List<C<?, ?>>
it seems to me I lost the generics types.
What is the correct way to do this collection?
Upvotes: 1
Views: 104
Reputation: 2121
I find a solution encoding the types constraint in a custom (un-generic) type.
so now I have these classes:
class MainLogic {
List<TypeHelper<?,?>> elements = new ArrayList<>();
<T1, T2 extends T1> void addElement(T1 e1, T2 e2) {
this.elements.add(new TypeHelper<T1,T2>(e1, e2));
}
void logic() {
for (TypeHelper<?, ?> element: elements)
element.logicHelper(this);
}
<T1, T2 extends T1> void logicHelper(T1 e1, T2 e2) {
// here finally I have the variables constrained
}
}
class TypeHelper<T1, T2 extends T1> {
T1 e1;
T2 e2;
void logicHelper(MainLogic ml) {
ml.logicHelper(e1, e1);
}
}
Upvotes: 0
Reputation: 33855
Since T2
is bounded in the declaration of C
, you will always retain the fact that it is a subtype of T1
even if you use wildcards. i.e. it is a characteristic of C
that the second type parameter extends the first.
So you can just use List<C<?, ?>>
.
You can already see that this works when you try to bind the generic parameters to type variables. e.g.:
public static <T1, T2> void m(List<C<T1, T2>> list) { ... }
^^-- Bound mismatch
You would need to use:
public static <T1, T2 extends T1> void m(List<C<T1, T2>> list) {...}
Or:
public static <T1> void m(List<C<T1, ? extends T1>> list) {...}
For the compiler to be happy.
Upvotes: 2