Reputation: 1933
I'm trying to add instances to the following EnumMap:
class ActiveG<D extends GData, T extends GTemplate> {
EnumMap<GStateType, GState<ActiveG<D,T>> map;
..
..
}
class TGData extends GData {...}
class TGTemplate extends GTemplate {....}
class ActiveTG extends ActiveG<TGData, TGTemplate> {
// fails with compilation error
super.states.put(GStateType.WAITING, new TGWaitingState<ActiveTG>(this));
...
...
}
The error I get:
The method put(GStateType, GState<ActiveG<TGData,TGTemplate>>) in the
type EnumMap<GStateType,GState<ActiveG<TGData,TGTemplate>>> is not
applicable for the arguments (GStateType, TGWaitingState<ActiveTG>)
Can anyone try to help me figure out what's missing to make it work?? Thanks!
Upvotes: 0
Views: 266
Reputation: 40036
In brief, Generics in Java is not covariance.
e.g. if you have
class Parent {...}
class Child extends Parent {...}
Foo<Child>
is NOT a Foo<Parent>
Go back to your code:
your enum map in ActiveTG
is expecting GState<ActiveG<TGData,TGTemplate>>
as value, but you are giving it a TGWaitingState<ActiveTG>
, which is a GState<ActiveTG>
.
Although ActiveTG
is-a ActiveG<TGData,TGTemplate>
, GState<ActiveTG>
is NOT a GState<ActiveG<TGData,TGTemplate>>
.
In order to solve it, you will need quite some change in the type params, like
class ActiveG<D extends GData,
T extends GTemplate,
E extends ActiveG<D,T>> {
EnumMap<GStateType, GState<E>> map;
}
or simply make map
with type EnumMap<GStateType, GState<? extends ActiveG<D,T>>
. This may not work very well in some situation, for example, you need to retrieve the result as a GState<ActiveTG>
instead of GState<ActiveG<D,T>>
Upvotes: 1