简体   繁体   English

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

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

I'm currently writing a grid-based puzzle game, and have run into a problem. 我正在写一个基于网格的益智游戏,并遇到了一个问题。

I have an abstract Sprite class where each Sprite represents some object on my map (a player, a wall, etc). 我有一个抽象的Sprite类,其中每个Sprite代表我的地图上的一些对象(玩家,墙壁等)。 This Sprite class has children (Item, Entity, Obstacle), and these children have children (Item has InventoryItem and InstantUseItem), and so on. 此Sprite类具有子项(Item,Entity,Obstacle),并且这些子项具有子项(Item具有InventoryItem和InstantUseItem),依此类推。 Only children without any further children are not abstract, so you can only instantiate concrete objects that you can find in-game (you can instantiate Sword and Arrow, but not Weapon - their parent object). 只有没有任何其他孩子的孩子才不是抽象的,所以你只能实例化你可以在游戏中找到的具体对象(你可以实例化剑和箭,但不能武器 - 他们的父对象)。

My problem is that I'm storing all the objects on Tiles (each map has width*height Tiles) in a Sprite ArrayList, and now I want to do something like find which Tile the Player object is on, or find all the Tiles that contain Enemy objects (or classes that inherit from them). 我的问题是我将所有对象存储在Tiles中(每个地图都有宽度*高度Tiles)在Sprite ArrayList中,现在我想做一些像找到Tile the Player对象的东西,或者找到所有的Tiles那个包含Enemy对象(或从它们继承的类)。

The problem is that, as far as I can tell, I can't do something akin to this in my Map or Tile object: 问题是,就我所知,我不能在我的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;
}

Even if I try to implement a static function in Sprite, I would need this (a kind of 'automatic covariance' amongst all of Sprite's children): 即使我尝试在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;
}

The other methods I have thought of involve: 我想到的其他方法包括:

  1. Making the latter method return an array of Sprites, then overriding this method in all children to return an array of children using covariance. 使后一种方法返回一个Sprite数组,然后在所有子项中重写此方法以使用协方差返回子数组。
  2. Making Sprite contain isWeapon(), isItem(), isEntity(), etc, (which all return false) then override these methods in the appropriate children. 使Sprite包含isWeapon(),isItem(),isEntity()等,(都返回false)然后在适当的子节点中覆盖这些方法。 I now use these methods instead of a unified isGivenType(Type t) method, or a unified static Type.isGivenType() method. 我现在使用这些方法代替统一的isGivenType(Type t)方法,或统一的静态Type.isGivenType()方法。

Making sure my program conforms to Object Oriented Principles, and remains easily extensible, is very important to this project. 确保我的程序符合面向对象的原则,并且易于扩展,对于该项目非常重要。 Is there any way to implement any of my solutions, or achieve my goal? 有没有办法实现我的任何解决方案,或实现我的目标?

It looks like this is what you want: 看起来这就是你想要的:

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

And then you can use it like this: 然后你可以像这样使用它:

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

Another way to do it would be to return a stream instead of a list: 另一种方法是返回流而不是列表:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM