返回一个预期超类的扩展类

时间:2011-12-13 00:11:50

标签: java class components

我目前正在使用组件模式开发游戏,并且总是想知道如何完成。 我有一个实体,实际上只是一袋组件。每个组件都扩展了Component类,它只具有一些基本功能。

扩展组件类,创建新组件,用于处理输入,图形等。现在出现了问题;当我试图从实体获取特定组件时,它总是返回基本的Component类,这阻止我使用特定的组件函数。

    public class GameEntity
{
    private ArrayList<Component> components;

    public GameEntity()
    {
        components = new ArrayList<Component>();
    }

    public void addComponent(Component component)
    {
        components.add(component);
    }

    public void update()
    {

    }

   public Component getComponent(Class type)
   {
       for (Component component : components)
       {
            if(component.getClass() == type)
            {
                //return component as Class;

            }
       }
       return null;
   }


    public void draw(Canvas canvas)
    {
        for (Component component : components)
        {
            component.update();
            component.draw(canvas);
        }
    }

}

一些示例组件:

  

public class GraphicsComponent扩展了Component {

     

公共位图位图;       public Rect currentFrameRect;       private ArrayList spriteAnimations;       public SpriteAnimation currentAnimation; public int x = 0; public int y = 50;上市   GraphicsComponent(){           spriteAnimations = new ArrayList(); }

/**
 * Adds image [converts to spriteanimation]
 * @param image
 */
public void addImage(Bitmap image, String label)
{
    Rect[] tmpRects = {new Rect(0, 0, image.getWidth(), image.getHeight())} ;
    addAnimation(new SpriteAnimation(
            image, tmpRects, label
    ));
}

public void addAnimation(SpriteAnimation spriteAnimation)
{
    spriteAnimations.add(spriteAnimation);

   if(currentAnimation == null)
   {
       currentAnimation = spriteAnimation;
   }
}


@Override
public void update()
{
   currentFrameRect = currentAnimation.frames[currentAnimation.currentFrame];
}
     

@Override public void draw(Canvas canvas){

    if(currentAnimation != null)
    {
        currentAnimation.draw(x, y, canvas);
    }     }
public int getWidth()
{
    return currentAnimation.frames[currentAnimation.currentFrame].width();
}

public int getHeight()
{
    return currentAnimation.frames[currentAnimation.currentFrame].height();
}
}


public class InteractiveComponent extends Component
{
    public GraphicsComponent graphics;

    public InteractiveComponent(GraphicsComponent graphics)
    {
        this.graphics = graphics;
    }

    public boolean isOver(int tapX, int tapY)
    {
        //left top right bottom
        if(tapX > graphics.x && tapX < graphics.x + graphics.getWidth() &&
           tapY > graphics.y && tapY < graphics.y + graphics.getHeight()
        )
        {
            return true;
        }
        return false;
    }

}

代码格式化似乎存在一些问题,但应该很清楚。 我无法访问graphicComponent中的getHeight()或者来自interactiveComponent的isOver()等任何特定函数,因为我只是返回了一个基本的Component。

我想根据传入 getComponent()的类返回 GraphicsComponent InteractiveComponent

5 个答案:

答案 0 :(得分:3)

你想要做的事情在架构上似乎对我很怀疑,但是尽管如此,它可以使用泛型以“干净”的方式完成,并且你已经将类对象作为类型令牌传递:

class Animals {
    List<Animal> animals = new ArrayList<Animal>();

    public <T extends Animal> T getAnimal(Class<T> type) {
        for (Animal animal : animals) {
            if (type.isAssignableFrom(animal.getClass())) {
                return type.cast(animal);
            }
        }
        return null;
    }
}

class Main {
    public static void main(String[] args) {
        Animals animals = new Animals();
        animals.getAnimal(Cat.class).meow();
        animals.getAnimal(Dog.class).bark();
    }
}

interface Animal {}

class Cat implements Animal {
    public void meow() {}
}

class Dog implements Animal {
    public void bark() {}
}

您可以==equals()而不是isAssignableFrom()检查,具体取决于您想要的确切行为。

答案 1 :(得分:2)

其他人建议将低价转型作为解决方案。我会说:重新设计

如果您发现自己需要向下倾斜,那么它表明您可能存在架构问题。事实上,你有。您希望访问每个对象,但不能以多态方式访问。因此,尝试通过超类型的容器访问特定对象是不自然的/无益的/低效的。

我建议:

class GameEntity {
    private GraphicsComponent graphics;
    private InteractiveComponent interactive;
    private SoundComponent sound;

    private List<Component> components;

    public GameEntity() {
        components.add(graphics);
        // etc.
    }

    public GraphicsComponent getGraphics() { return graphics; }
    // etc.

    public void draw() {
        for (Component c : components) {
            ...
        }
    }
}

答案 2 :(得分:0)

以这种方式收到组件后,您必须将其强制转换为类类型。然后你可以访问getHeight()等。该对象根本不知道是一个graphicComponent,但它是。

答案 3 :(得分:0)

好吧,该函数返回Component。如果您知道您已请求特定组件,请转换结果:

GraphicsComponent gc = (GraphicsComponent)(gameEntityInstance.getComponent(GraphicsComponent.class));

答案 4 :(得分:0)

当你致电getComponent()并从该方法中删除Class参数时,最好的选择是投票。

因此,getComponent会返回Component,可以投放到InteractiveComponentGraphicsComponent中:

public Component getComponent() { /* its contents */ };

GraphicsComponent gc = (GraphicsComponent)...getComponent();
InteractiveComponent ic = (InteractiveComponent)...getComponent();