Foreach通过不同的对象,但都可以实现相同的界面?

时间:2011-06-09 16:52:37

标签: java

假设我有这个

interface Movable
{//some stuff}

我有

class Car implements Movable
{//some stuff}

也许我有

class Bike implements Movable
{//some stuff}

我注意到如果我有这个:

ArrayList<Movable> movableThings = new ArrayList<Movable>();
movableThings.add(some kind of Car)
movableThings.add(some kind of Bike)
movableThings.add(some kind of Bike)

这可以称为:

for(Movable m: movableThings)

但是,如果我称之为“不相容”类型:

for(Bike b: movableThings)

有人可以解释,也许可以提供更好的方法吗? 我知道我可以使用foreach Movable m:movableThings然后使用instanceof来检查自行车但是还有其他方法吗?

编辑:好的,谢谢你澄清一下......所以我猜我要么使用instanceof,要么重新设计我的游戏

4 个答案:

答案 0 :(得分:9)

我不建议使用instanceof。实现公共接口的两种类型的整体是,在使用接口时,消费者代码不应该关注具体的实现。当我在instanceof之外看到equals()时,我会非常怀疑。

如果您想要来自不同实现的不同行为,请使用多态分派而不是instanceof

interface Movable
{
    void move();
}

class Bike implements Movable
{
    public void move()
    {
        // bike-specific implementation of how to move
    }
}

class Car implements Movable
{
    public void move()
    {
        // car-specific implementation of how to move
    }
}

将针对每种类型调用特定于实现的方法:

for (Movable m : movableThings)
{
    m.move();
}

如果您只想迭代Bike个类型,请创建一个仅包含Bike的集合:

List<Bike> bikes = new ArrayList<Bike>();
// etc...

for (Bike bike : bikes)
{
    // do stuff with bikes
}

N.B。您几乎应该始终将集合声明为List(接口)而不是ArrayList(接口的实现)。

另见

如果您还没有,可能还想阅读The Java Tutorials: Interfaces and Inheritance

答案 1 :(得分:2)

您需要使用instanceof。您可能希望编写一个过滤器函数以使其可重用。

话虽如此,这可能是您希望使用继承来允许以相同方式在两个类上调用相同方法的情况。

答案 2 :(得分:2)

因为您的ArrayList被定义为

 ArrayList<Movable>

您的ArrayList的get方法将返回Movable类型。如果您确定运行时类型(使用instanceof进行检查),则需要手动强制转换它。

for(Movable m: movableThings){
      if (m instanceof Car){
            Car car = (Car)m;
      }
}

答案 3 :(得分:0)

这是Google Guava或类似的集合库真正有益的地方。你会发现它有很多其他的用途,因此在你的项目中证明这一点并不困难。

在番石榴:

for (Bike bike : Iterables.filter(movableThings, Bike.class) ) {
    //now you only have bikes
}