I am currently building a game in java(turn based RPG) and am facing a problem in inventory UI. Perhaps my problem is well known or has a simple solution, but having never had any training, I will still ask the question.
While displaying the inventory after selecting an item I check if that item implements the SpecificItemWorker
interface , that is, acts on a specific GameObject
that has to be passed in to its takeAction()
method. While selecting that object which has to be passed, I display all the possible candidate objects for the user to select. For example, suppose the user selects a UpgradeParchment
that acts on any object that implements Upgradable
interface. Here, I initiate a ItemSelector
that displays all the items in the inventory that implements Upgradable
. However with a different class , the interface that the object needs to implement in order to be a possible candidate will differ.(Note that some objects act on the game environment rather than on a specific object, but we are not considering that case here.).Now instead of hard-coding the possible interfaces in a switch case
statement , i want it to be dynamic.I tried to use generics, but it does not allow to check if an object is an instanceof
of the Type parameter. The following code gives a compile error:
package ui;
import objects.Collectable;
public class ItemSelector<T> {
public void test(Collectable ob) {
if (ob instanceof T) {// compile error
// do work
}
}
}
Does anyone know how this can be achieved?Thanks for any help.
Looking for a speedy reply, Thanks.
EDIT : The parameter in the testAction()
method will be of type Collectable
as in my inventory class, there is only a list of Collectable
objects.Similarly, in my test method , I have updated the types.Although it is a minor change, sorry for any inconvenience. Collectable
is also an interface.
Due to runtime type erasure, you need to provide what's called a type token to the class:
public class ItemSelector<T> {
private final Class<T> clazz;
public ItemSelector(Class<T> clazz) {
this.clazz = clazz;
}
public void test(GameObject ob) {
if (clazz.isInstance(ob)) {// use token to check type
// do work
}
}
}
This requires a class object to be passed to the constructor, usually by passing a class literal, eg MyClass.class
There is a way to check the type with class.getTypeName().
I assume the SpecificItemWorker is a game object as shown in the code.
package stackoverflow.question39718130;
public class SpecificItemWorker extends GameObject {
}
package stackoverflow.question39718130;
public class ItemSelector<T> {
private T t;
public ItemSelector(final T t) {
this.t = t;
}
public T getT() {
return t;
}
public void test(final GameObject ob) {
/*if (ob instanceof T) {// compile error
// do work
}*/
if (t.getClass().getTypeName() == ob.getClass().getTypeName()) {
System.out.println("Grab item.");
} else {
System.err.println("No item found.");
}
}
}
There is a test example to pass the GameObject
.
package stackoverflow.question39718130;
public class GameObjectTest {
public static void main(final String[] args) {
specificItemWorkerTest();
}
public static void specificItemWorkerTest() {
final GameObject specificItemWorker = new SpecificItemWorker();
final ItemSelector<GameObject> selector = new ItemSelector<>(specificItemWorker);
selector.test(specificItemWorker);
}
}
I hope I understood you right with the SpecificItemWorker
. Please let me know if this fits to your solution.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.