I have a question about generics.
I am trying to create a generic state machine.
so these are the classes:
The problem is with SampleChild1 class.
whenever I try to pass a SampleChild1State1 Object into the setState method of BaseClass I get the following error:
The method setState(State<capture#2-of ? extends BaseClass>) in the type StateMachine<capture#2-of ? extends BaseClass> is not applicable for the arguments (SampleChild1State1)
Is there anyway to solve this problem? to make my StateMachine class generic so I can declare it only in BaseClass?
Or I will have to have a new specific Object of StateMachine class in any subclass of Baseclass?
1. SampleChild1State1 is interface? If so, it must extend State interface if not, must defined as class
2. SampleChild1 must extend BaseClass (as State interface can only accept <T extends BaseClass>)
3. The setState method is expected to accept object of StateMachine of type T which extends BaseClass only. Whereas, you are trying to pass SampleChild1State1 which is (if a class) implementation of State itself.
Leroy, please PostRealCode. You may choose to omit parts that aren't necessary, but with your current code I have to fix too many compiler errors before I get to the error you get (actually I'm not even there yet).
Rob Prime, once again you are right..
really sorry for the inconvenience...
Here is the code I have, I omitted unrelevant stuff:
This is what I get:
The method setCurrentState(EntityState<capture#2-of ? extends BaseGameEntity>) in the type EntityStateMachine<capture#2-of ? extends BaseGameEntity> is not applicable for the arguments (ItemUnidentifiedState)
OK, now I could pinpoint the exact location of the error.
"this.states" is an EntityStateMachine<? extends BaseGameEntity>. And that wildcard is the problem. EntityStateMachine<T> expects a T for its setCurrentState method. However, what is T in this.states? You don't know. It could be BaseGameEntity, InfObject, or anything else that extends BaseGameEntity.
I suggest you make BaseGameEntity generic as well. The class definitions then become as follows:
One more change is required, in BaseGameEntity:
This now matches the initialization of states inside Item:
After these changes I could compile your code.
The other alternative is to use I haven't tested if that would compile. If so, that would actually be easier.
As for that line. The T is the new generic type, as usual. Because you had "? extends BaseGameEntity" the T must be bound as well. That would lead to "T extends BaseGameEntity". However, BaseGameEntity is now generic, so the compiler will complain about a raw type. You must fill in the generic type. There are actually more alternatives:
- BaseGameEntity<?> -- any BaseGameEntity is allowed. This would allow Item to extend InfObject<BaseGameEntity>, InfObject<InfObject>, InfObject<Item>, or any other sub class of BaseGameEntity.
- BaseGameEntity<T> -- Item can only extend InfObject<Item>
- BaseGameEntity<? extends T> -- Item can only extend InfObject<Item> and InfObject<X> where X is any sub class of Item
- BaseGameEntity<? super T> -- like ? but limited to BaseGameEntity, InfObject and Item
- BaseGameEntity<X> with X being a hard coded class. You definitely do not want that though.
I think that trying out to remove the "? extends" from states would actually be worth checking out. It will make your classes less complex.
Thanks all for the help, especially Rob, you have been a great help for me.
It works perfect now, and I updated other classes I wrote.
Unfortunately, your suggestion seems the only way the code will compile.
Thanks a lot
Let's get him boys! We'll make him read this tiny ad!
a bit of art, as a gift, that will fit in a stocking