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 Bike
s:
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
}
精彩评论