Поиск всех объектов, которые являются потомками данного типа в Java - PullRequest
0 голосов
/ 17 сентября 2018

Я сейчас пишу головоломку на основе сетки и столкнулся с проблемой.

У меня есть абстрактный класс Sprite, где каждый Sprite представляет некоторый объект на моей карте (игрок, стена,так далее).У этого класса Sprite есть дочерние элементы (Item, Entity, Obstacle), а у этих дочерних элементов есть дочерние элементы (Item имеет InventoryItem и InstantUseItem) и т. Д.Только дети без каких-либо дополнительных детей не являются абстрактными, поэтому вы можете создавать экземпляры только конкретных объектов, которые вы можете найти в игре (вы можете создавать экземпляры Sword and Arrow, но не Weapon - их родительский объект).

Моя проблема в том,что я храню все объекты на тайлах (каждая карта имеет плитки ширины * высоты) в массиве спрайтов, и теперь я хочу сделать что-то вроде поиска объекта Tile the Player или найти все тайлы, содержащие объекты Enemy.(или классы, которые наследуются от них).

Проблема в том, что, насколько я могу судить, я не могу сделать что-то похожее на это в моем объекте Map или Tile:

public ArrayList<t> findAllSpritesOfType(Type t) {
    ArrayList<t> sprites = new ArrayList<t>();
    for(Sprite s : this.getSprites()) {
        if(s instanceof t) {
            sprites.add((t) s); //Add after casting to right class
        }
    }
    return sprites;
}

Даже если я попытаюсь реализовать статическую функцию в Sprite, мне понадобится это (своего рода «автоматическая ковариация» среди всех детей Sprite):

public static ArrayList<this.Type> getSpritesOnTile(Tile t) {
    ArrayList<this.Type> sprites = new ArrayList<this.Type>();
    for(Sprite s : t.getSprites()) {
        if(s instanceof this.Type) {
            sprites.add((this.Type) s); //Add after casting to right class
        }
    }
    return sprites;
}

Другие методы, о которых я думал, включают:

  1. Заставить последний метод вернуть массив спрайтов, затем переопределить этот метод во всех дочерних элементах, чтобы вернуть массив дочерних элементов, используя коварианецe.
  2. Если Sprite содержит isWeapon (), isItem (), isEntity () и т. д. (которые все возвращают false), то переопределяет эти методы в соответствующих дочерних элементах.Теперь я использую эти методы вместо унифицированного метода isGivenType (Type t) или унифицированного статического метода Type.isGivenType ().

Убедитесь, что моя программа соответствует объектно-ориентированным принципам и легко расширяется, очень важно для этого проекта.Есть ли способ реализовать какое-либо из моих решений или достичь моей цели?

1 Ответ

0 голосов
/ 17 сентября 2018

Похоже, это то, что вы хотите:

public <T extends Sprite> ArrayList<T> findAllSpritesOfType(Class<T> clazz) {
    ArrayList<T> sprites = new ArrayList<>();
    for(Sprite s : this.getSprites()) {
        if(clazz.isInstance(s)) {
            sprites.add((T) s);
        }
    }
    return sprites;
}

И тогда вы можете использовать его так:

List<Item> items = findAllSpritesOfType(Item.class);

Другой способ сделать это - вернуть поток вместо списка:

public <T extends Sprite> Stream<T> findAllSpritesOfType(Class<T> clazz) {
    return getSprites().stream().filter(clazz::isInstance).map(clazz::cast);
}
...