18

我有一个可损坏的接口,如下所示

public interface Damageable {
    public void handleCollision(float impulse);
}

实现此接口的类 BaseObject

public class BaseObject implements Damageable

现在在第三类中,我有一个 BaseObject 类型的 ArrayList

public class ObjectManager {    
    public ArrayList<BaseObject> bodies;

我想要做的是将 ArrayList 主体传递给另一个接受 ArrayList 的类的方法

public CollisionManager( ArrayList<Damageable> _bodies) {
        bodies = _bodies;
}

Java 不允许我在 body 类型为 ArrayList 且 BaseObject 实现 Damageable 的情况下执行 new CollisionManager(bodies)

我试过铸造。说不能从 ArrayList<BaseObject>ArrayList 转换为 ArrayList 也尝试过使用Class<? extends Damageable>,但后来我无法调用接口 Damageable 中声明的方法。如何传递 ArrayList?

4

3 回答 3

43

你必须明确你的泛型。因此,您必须通知编译器您的泛型类型不必Damagable本身,而是可以扩展 Damagable

public CollisionManager(ArrayList<? extends Damagable> bodies) {

顺便说一句,请注意我将您的变量更改为bodies而不是_bodies. 下划线不是标准 Java 编码约定的一部分。


根据OP的评论进行编辑

假设您有一个名为Damagable. 告诉编译器<? extends Damagable>说它不必是Damagable. 类型extend没关系。_ 否则,编译器假定您有一个完全正确的. DamagableDamagable

当您将其视为接口时,它没有多大意义Damagable,因为您不会有Damagable. 但它们的工作方式基本相同。

您必须记住,您使用的是 Java类型,而不是类。Java 的类型语法和结构不如它的类结构健壮。没有关于implements类型的概念。


最后一轮编辑

最后,我应该注意,通常最好为方法/构造函数参数和方法返回类型使用接口。这允许您和使用您的方法的人使用您喜欢的任何实现,并允许您随意更改您的实现。

因此,通过这些修订,您将拥有:

public CollisionManager(List<? extends Damagable> bodies) {
于 2012-05-23T02:15:15.020 回答
2

试试ArrayList<? extends Damageable > _bodies

这表示您想要一个 ArrayList 包含一个Class可以扩展的(很好的实现)Damageable

于 2012-05-23T02:12:56.003 回答
2

其他人无疑会从 Java 语法的角度指出技术解决方案。

我只想提一些您可能应该考虑的设计问题:

  • 你的 BaseObject 实现了 Damageable。这意味着所有 BaseObject 都是可损坏的。那么为什么不做一个CollisionManager(ArrayList<BaseObject>)呢?除非您打算在其他地方使用 Damageable(即有些东西是 Damageable 但不是 BaseObjects),否则这似乎是一种不必要的抽象。
  • 通常对于游戏/模拟中的碰撞检测,您可能希望使用空间数据结构进行碰撞检测(例如八叉树、四叉树或 AABB 树)而不是 ArrayList。在 ArrayList 中搜索冲突是一个 O(n^2) 算法。如果您有很多活动对象,这将成为一个大问题。
  • 可损坏似乎是一个坏名字,因为该功能与碰撞检测而不是损坏有关 - Collidable 不是更好吗?
于 2012-05-23T02:20:35.110 回答