Преобразование Java из объекта в подкласс

Вот мой код для Scene.java. Он имеет разные типы объектов, все из которых включены в один общий ArrayList под названием targets. Все они используют метод toString(), который возвращает свой идентификатор. Я хочу использовать список targets, чтобы определить, есть ли какой-либо объект в сцене, который соответствует данному идентификатору, независимо от его типа:

ArrayList<NPC> npcs = new ArrayList<NPC>();
ArrayList<Item> items = new ArrayList<Item>();
ArrayList<EnviromentalObject> enviromental_objects = new ArrayList<EnviromentalObject>();

ArrayList<Object> targets;

public Object check_for_target(String target_name){
    targets.addAll(npcs);
    targets.addAll(items);
    targets.addAll(enviromental_objects);
    for (Object target : targets){
        if (target.toString() == target_name){
            return target;
        }
    }
    return null;

Вот код в Game.java, который проверяет данный идентификатор. Если есть совпадение текущей сцены, я хочу знать тип объекта и рассматривать его как его истинный тип. Прямо сейчас у меня есть следующий код, и я знал, что это не сработает, но, возможно, это поможет мне разобраться.

Object target = current_scene.check_for_target(target_name);
        if (target == null){
            System.out.println(UNRECOGNIZED_TARGET_MESSAGE);
        } else {
            String target_type = target.getClass().getName();
            target = (target_type) target;
        }

Каким будет правильный способ получения типа объекта, а затем возможность использования методов этого объекта? Сейчас мне дают только методы Object. Создать суперкласс для NPC, Item и EnviromentalObject?

Ответ 1

В принципе, вы можете проверить, является ли объект экземпляром определенного класса.

это может быть примерно так:

if( target instanceof NPC) {
    System.out.println("target  is a NPC");
}
else if( Target instanceof Item) {
    System.out.println("target is an Item");
}

if( target  instanceof EnviromentalObject) {

    System.out.println("target is EnviromentalObject"); 
}

Изменить: как мы говорили в комментариях, я думаю, вы можете изменить свой код, чтобы достичь лучшего решения. Вышеприведенный код по-прежнему работает, но очень полезно использовать Шаблоны проектирования, которые известны как лучшие методы программирования. В этой ситуации подумайте об использовании интерфейса Java и определите методы совместного использования, которые каждый объект мог бы реализовать по своей потребности. Простейшим способом они печатают свой идентификатор. Пусть используется пример:

public interface SceneThings() {

    public void printIdentifire();

    public String doSomeOtherThings();

}

Каждый объект может реализовать указанный выше интерфейс, например:

public class Item implements SceneThing {

...

public void printIdentifire(){

//print its identifier here.
System.out.print("ID:ITEM###");

}

public String doSomeOtherThings(){

    //do some other works !!!
}
...
}

для других предметов, как указано выше. И тогда вы можете использовать один массив, чтобы не беспокоиться о своем классе происхождения следующим образом:

ArrayList<SceneThings> targets = new ...

SceneThing  obj = new Item();
targets.add(obj);

Надеюсь, это поможет вам определить лучшее решение в вашем случае.

Ответ 2

Один из способов, как это можно было бы сделать, чтобы объявить суперкласс или интерфейс Target и использовать его для хранения массива целей, полного образца кода с абстрактным классом:

ArrayList<NPC> npcs = new ArrayList<NPC>();
ArrayList<Item> items = new ArrayList<Item>();
ArrayList<EnviromentalObject> enviromental_objects = new ArrayList<EnviromentalObject>();

ArrayList<Target> targets;

public Target check_for_target(String target_name) {
    targets.addAll(npcs);
    targets.addAll(items);
    targets.addAll(enviromental_objects);
    for (Target target : targets) {
        if (target.toString().equals(target_name)) {
            return target;
        }
    }
    return null;
}

private abstract class Target {}
private class NPC extends Target {}
private class Item extends Target {}
private class EnviromentalObject extends Target {}