查找Java中给定类型的子对象的所有对象

时间:2018-09-17 06:57:15

标签: java java-8 polymorphism covariance

我目前正在编写基于网格的益智游戏,但遇到了问题。

我有一个抽象的Sprite类,其中每个Sprite代表我地图上的某个对象(玩家,墙壁等)。此Sprite类具有子项(Item,Entity,Obstacle),并且这些子项具有子项(Item具有InventoryItem和InstantUseItem),依此类推。只有没有其他子级的子级不是抽象的,因此您只能实例化可以在游戏中找到的具体对象(可以实例化Sword and Arrow,而不能实例化Weapon-它们的父级对象)。

我的问题是我将所有对象存储在Sprite ArrayList中的Tiles(每个地图都有width * height Tiles)上,现在我想做一些事情,例如查找Player对象在哪个Tile上,或全部找到包含敌人对象(或从其继承的类)的图块。

问题是,据我所知,我无法在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. 使后一种方法返回一个Sprites数组,然后在所有子级中重写此方法以使用协方差返回一个子级数组。
  2. 使Sprite包含isWeapon(),isItem(),isEntity()等(均返回false),然后在适当的子代中重写这些方法。我现在使用这些方法来代替统一的isGivenType(Type t)方法或统一的静态Type.isGivenType()方法。

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

1 个答案:

答案 0 :(得分:2)

看起来这就是您想要的:

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