在 Java 中查找属于给定类型 Child 的所有 Objects

Finding All Objects that are a Child of a Given Type in Java

我目前正在编写一个 grid-based 益智游戏,遇到了 运行 个问题。

我有一个抽象的 Sprite class,其中每个 Sprite 代表我地图上的一些 object(玩家、墙等)。这个 Sprite class 有 children (Item, Entity, Obstacle),而这些 children 有 children (Item 有 InventoryItem 和 InstantUseItem),等等。只有 children 没有任何进一步的 children 不是抽象的,所以你只能实例化你能找到的具体 objects in-game (你可以实例化 Sword 和 Arrow,但不能实例化 Weapon - 他们的 parent object).

我的问题是我将所有 objects 存储在 Sprite ArrayList 中的 Tiles(每个地图都有宽度*高度的 Tiles)上,现在我想做一些事情,比如找到播放器的哪个 Tile object 开启,或找到所有包含敌人 object(或继承自它们的 class)的图块。

问题是,据我所知,我不能在我的 Map 或 Tile 中做类似的事情 object:

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 children 中的一种 'automatic covariance'):

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. 使后一种方法return成为精灵数组,然后使用协方差在所有children到returnchildren数组中覆盖此方法。
  2. 让 Sprite 包含 isWeapon()、isItem()、isEntity() 等(所有 return 为 false)然后在适当的 children 中覆盖这些方法。我现在使用这些方法而不是统一的 isGivenType(Type t) 方法或统一的静态 Type.isGivenType() 方法。

确保我的程序符合 Object 面向原则,并且易于扩展,这对这个项目来说非常重要。有什么方法可以实现我的任何解决方案,或者实现我的目标吗?

看来这就是你想要的:

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);

另一种方法是return流而不是列表:

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