I've been working on a project in Java lately that uses a Generic-Best Search Algorithm. To make the Algorithm itself Generic, I used a bunch of Generics on all of the Classes used in the Algorithm.
Here's all of the Class/Interface Declarations:
public class StateSearch<E extends AbstractState<E>>
public class AbstractState<E> implements State<E>
public class StateNode<E extends AbstractState<E>> implements Comparable<StateNode<E>>
public class StateQueue<E extends AbstractState<E>>
public interface State<E> extends ComparableState<E>>
Now in theory, all of this works just fine. However, when I apply the Algorithm, I plan for 'E' to be some sort of Game State (Say a Checkers Board, Solitaire Game, Pathfinder, what-have-you). Thus, I created the following Class:
public class GameState extends AbstractState<String>
My intention for this particular setup is to have the GameState be a container for a String which represents the State of a particular Game. However, this causes an issue for trying to create a StateSearch using the following code:
new StateSearch<GameState>(new GameState(initialState), new GameState(goalState));
I end up getting a Bound Mismatch Error, stating that GameState is not a valid substitute for <E extends AbstractState<E>>. Now, I believe I understand why this is happening. My thoughts is because GameState extends AbstractState<String>, and not AbstractState<E>.
Unfortunately, I do not want my GameState Class to have a Generic Type. It is designed to be implemented to actually do something, thus the switch from Generics to Strings. For example, I might want to create a GameState Class in an entirely different project that uses Integers for its implementation.
Given the Methods, Variables, and Operations I use and perform within the GameState Class, it cannot be Generic.
My question after all of this: Is there a way to implement my GameState Class as a Non-Generic Class in such a way that it satisfies the Bounding Requirements placed by my StateSearch Class?
I wouldn't mind if I had to change some of the Class Declarations. The point is that I need the Algorithm to be Generic, and the Implementation to be Non-Generic. The GameState Class needs to be the point at which I transition between the two.
GameState Class to function as a the implementation of a certain Game. The AbstractState and State interfaces are meant to allow me to build a State Search Algorithm without requiring the actual implementation. Settings things up in this manner allow me to apply this setup across multiple games.
The StateSearch Class basically just pulls States off of my StateQueue, which is just a Vector of AbstractState Classes that is ordered by a priority system (hence the Comparable implementation). The manner of which the State Tree is expanded is by using the getNextState() function from the AbstractState Class. This is fine and all, but the getNextState() function basically grabs the best state from my getSuccessors() function, which can only be defined in the GameState Class. Everywhere else it's just Abstract.
I cannot define the getSuccessors() function in a Generic manner, as it is purely based upon implementation. This function is meant to return all possible states from the current state. For example, if the game was Tic-Tac-Toe, the getSuccessors() function would return a list of Game States where each State represents a possible move.
The GameState Class also contains a getEstimatedCost() and getRunningCost() which basically act as the h(x) and g(x) functions respectively. This too may only be defined in the GameState Class, as both depend upon Implementation.
The way you have things defined is effectively an implementation of the Curiously recurring template pattern
When you have:
public class StateSearch<E extends AbstractState<E>>
It means that to use a GameState as its Generic type, it would need to be defined as:
public class GameState extends AbstractState<GameState>
As for what you really need, it's unclear why you need generics. Why wouldn't a GameState interface suffice?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With