【问题标题】:Java Parametric Polymorphism exampleJava 参数多态性示例
【发布时间】:2012-11-15 19:39:57
【问题描述】:

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

    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();             
    }

【问题讨论】:

  • 理想情况下,您将对可以在基类中声明并在子类中覆盖的每个项目执行类似的操作(例如speak())。那么你不需要担心类型。如果您按原样继续,那么是的,您需要强制转换以调用该方法。 (我有意识地排除了使用反射调用方法的选项)
  • 除非将bark()fly() 移至超类Animal,否则无法避免。

标签: java generics polymorphism


【解决方案1】:

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

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();
}

【讨论】:

    【解决方案2】:

    你不应该有这样的列表。否则instanceof(或.getClass()),后跟向下转换是唯一的选择。

    【讨论】:

    • 你是说把它们分成两个列表吗?
    【解决方案3】:

    使用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() 方法,那么您不会尝试在所有 Animal 实例上调用 fly() 方法...您将有一个不一样的List&lt;Bird&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-11
      • 2016-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-22
      • 1970-01-01
      • 2010-09-16
      相关资源
      最近更新 更多