Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Foreach through different objects but all implement same interface possible?

Tags:

java

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(Movable 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

like image 606
some Java amateur Avatar asked Jun 09 '11 16:06

some Java amateur


2 Answers

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;
      }
}
like image 24
Heisenbug Avatar answered Sep 18 '22 12:09

Heisenbug


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.

like image 72
Matt Ball Avatar answered Sep 20 '22 12:09

Matt Ball