在Java中遍历父类的ArrayList时使用Subclass方法

Posted

技术标签:

【中文标题】在Java中遍历父类的ArrayList时使用Subclass方法【英文标题】:Using Subclass method when iterating through ArrayList of parent class in Java 【发布时间】:2013-01-03 11:33:49 【问题描述】:

在这个循环中,我正在遍历 Entity 类型的 ArrayList,其中包含 Entity 类型的对象以及 Projectile 类型的对象,后者扩展了 Entity。如果对象是 Projectile 的实例,我希望执行以下代码。但是,getVelocity() 方法仅在子类 Projectile 中,而不在 Entity 中。所以我无法编译下面的代码。

我可以想办法解决这个问题,例如使用单独的 ArrayList。但是,关键是将所有实体保留在一个全局列表中,而不是将它们分开。这个问题有简单的解决方案,还是我需要改变我的代码结构?

for (Entity f: glo.getList()) 
           if (f instanceof Projectile)
              f.setX(f.getVelocity()/rawFPS);
        

【问题讨论】:

【参考方案1】:

这似乎是一个循环,在游戏引擎的每一次滴答声中都会以某种方式更新您的实体。

在我看来,更清洁的解决方案是:

class Entity 
  ...
  public void update() 
  ...


class Projectile extends Entity 
  ...
  @Override
  public void update() 
    setX(velocity/rawFPS);
  
  ...

我不知道您的架构,您可能需要也可能不需要将rawFPS 传递给update()。 (正如@Naveen 非常正确地指出的那样,这不是很干净,所以如果可以的话,请避免使用它)。此外,如果您的 Entity 是抽象的,本身没有任何功能,请首先考虑将其设为 interface

【讨论】:

+1 这是一个很好的面向对象的方法。让对象在知道如何更新/渲染时自行更新/渲染,必要时可以通过使用内部/非标准 API 受益。 我没有想过拥有独立的更新方法。鉴于我的其余代码,我将研究它是否可行。 嗯...将rawFPS 传递给所有实体闻起来有点奇怪,因为大多数Entitys 会忽略它。 @Navin 好吧,这取决于。在游戏中,大多数需要更新的实体都会根据经过的时间进行更新,因此实际上大多数实体都需要rawFPS。但我同意你的看法:如果可以,最好避免这种情况。 传递更新程序并使用特定于类型的回调。这将使它成为非常接近访客模式的双重调度。【参考方案2】:

您必须将其转换为 Projectile 才能编译。试试这个:

for (Entity f: glo.getList()) 
           if (f instanceof Projectile)
              f.setX(((Projectile)f).getVelocity()/rawFPS);
        

这是因为 java 总是检查对象声明的类型;在您的情况下,这是Entity

您可能想要添加一个@SuppressWarnings("unchecked"),以便您的 IDE 和阅读您的代码的任何人都知道未经检查的强制转换是故意的。

【讨论】:

【参考方案3】:

即使if(f instanceof Projectile) 是真的,你的引用是Entity 类型的,它不知道你在子类中声明了什么,所以编译失败

Entity 类中提供具有相同签名的空白方法,而不是在子类中提供 override 并删除 instanceof 检查,如果它适合您的类模型

使用强制转换

if(f instanceof Projectile)
  ((Projectile)f).setX(..);

【讨论】:

【参考方案4】:

Entity 确实应该是一个interface,并在其上定义了一个getVelocity() 方法。当然,您可以解决问题并进行投射,但请问问自己,对于您正在构建的内容,正确的逻辑模型是什么。

【讨论】:

我不是反对者,但我猜这是因为Entity 可能没有速度,所以给它一个getVelocity() 是没有意义的。【参考方案5】:

说真的,伙计们?很烂的例子。每一个 Java 指南都会告诉你这一点。

这里出了点问题:您正在循环一组实体并使用另一个数据项 FPS 更改子集(子类实例)的内部状态。如果您在构建 Projectile 时没有 FPS,那么稍后让这个外部类注入它似乎有点随机。只在 FPS 上调用一个集合然后更新位置可能会更干净。

外部类可能只需要 Projectiles。

【讨论】:

instance of sucks 真的吗?这个问题正是你使用instance of的那种情况。 我倾向于同意 Rob 的观点,instanceof 确实很烂。我没有在回答中提到那部分。 嗯...为什么是suck? 因为它不是面向对象的。如果您使用的是实例,则您的模型有缺陷。 第二个链接,老兄:来自 Google 的javapractices.com/topic/TopicAction.do?Id=31。

以上是关于在Java中遍历父类的ArrayList时使用Subclass方法的主要内容,如果未能解决你的问题,请参考以下文章

java中list和arraylist的区别

java面向对象特征

在java中this和super的使用

在遍历 ArrayList 时获取 java.util.ConcurrentModificationException

18.面向对象-----super关键字

java 里的 Collection接口有啥作用