开发者

Foreach through different objects but all implement same interface possible?

Suppose I have this

interface Movable
{//some stuff}

And I have

class Car implements Movable
{//some stuff}

And also maybe I have

class Bike implements Movable
{//some stuff}

I noticed that if I had this:

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

This can be called:

for(Mo开发者_如何学编程vable m: movableThings)

But if I call this I get incompatible types:

for(Bike b: movableThings)

Can someone explain, and maybe offer a better way? I know I can use foreach Movable m: movableThings and then use instanceof to check for Bikes but is there another way?

Edit: alright thanks for clarifying guys... so I guess I either use instanceof or redesign my game


I would not recommend using instanceof. The whole point of two types implementing a common interface is that, when using the interface, consumer code shouldn't be concerned with the specific implementation. I tend to get very suspicious when I see instanceof outside of equals().

Use polymorphic dispatch instead of instanceof if you want different behaviors from different implementations:

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

The implementation-specific method will be called on each type:

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

If you only want to iterate over Bike types, create a collection that only consists of Bikes:

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

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

N.B. You should almost always declare the collection as a List (an interface) rather than an ArrayList (an implementation of the interface).

See also

  • Avoiding instanceof in Java
  • Avoiding instanceof when checking a message type
  • How does one use polymorphism instead of instanceof? (And why?)
  • Avoiding 'instanceof' in Java
  • when should we use instanceof and when not

If you haven't already, you might also want to read though The Java Tutorials: Interfaces and Inheritance.


Because your ArrayList is defined to be

 ArrayList<Movable>

the the get method of your ArrayList will return a type Movable. You need to cast it manually if you are sure about the runtime type (use instanceof to check it).

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


You do need to use instanceof. You may want to write a filter function to make it reusable.

That being said, this is probably a case where you want to use inheritance to allow the same method to be called on both classes in the same way.


This is where Google Guava or a similar collection library can be really beneficial. You'll find tons of other uses for it so it's not a hard thing to justify including in your project.

In Guava:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜