0

我有一个关于参数多态性的问题。如果我有一个混合了子类型的集合,如何确定实际类型并避免强制转换。例如

    class Animal{

    }

    class Bird extends Animal{
          void fly(){}
    }

    class Dog extends Animal{
          void bark(){}
    }

    ArrayList<Animal> list = new ArrayList<Animal>();

问题是当我遍历 Animal 集合时如何知道哪个是哪个。我是否需要每次都使用 instanceof 来检查实际类型?

    for(Animal animal : list){
          if(animal instanceof Dog){
                ((Dog) animal).bark();
          } 
          else ((Bird) animal).fly();             
    }
4

3 回答 3

6

如果你需要这样做,那就意味着这是一个常见的动作。你通常会有这个:

abstract class Animal {
     abstract void act();
}

class Bird extends Animal{
      void fly(){}
      void act(){
         fly();
      }
}

class Dog extends Animal{
      void bark(){}
      void act(){
         bark();
      }
}

在您的循环中,您只需调用该act方法:

for(Animal animal : list){
    animal.act();
}
于 2012-11-15T19:42:06.570 回答
0

你不应该有这样的清单。其他instanceof(或.getClass()),后跟向下转换是唯一的选择。

于 2012-11-15T19:43:50.660 回答
0

使用instanceof会破坏泛型的目的。泛型的重点是定义行为,这样您就不必关心类型是什么。例子:

public interface Animal {
    void speak();
    void fly();
}

public class Dog implements Animal {
    public void speak() {
        System.out.println("Woof!");
    }
    // Do nothing!
    public void fly() { }
}

public class Bird implements Animal {
    public void speak() {
        System.out.println("Tweet!");
    }
    public void fly() {
        System.out.println("I'm flying!!");
    }
}

public static void main (String[] args) {
    // list populating removed
    for(Animal animal : list) {
        animal.speak();
        animal.fly();
    }
}

看?您实际上并不关心动物在运行时是什么类型。你让对象做他们应该做的事情。

顺便说一句,如果您确实只想Bird拥有一个fly()方法,那么您就不会尝试在...fly()的所有实例上调用该方法,Animal您会有不同的List<Bird>

于 2012-11-15T19:45:38.950 回答