Java参数多态性示例

Java参数多态性示例,java,generics,polymorphism,Java,Generics,Polymorphism,我有一个关于参数多态性的问题。如果我有一个混合了子类型的集合,如何确定实际类型并避免强制转换。比如说 class Animal{ } class Bird extends Animal{ void fly(){} } class Dog extends Animal{ void bark(){} } ArrayList<Animal> list = new ArrayList<

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

    class Animal{

    }

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

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

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

如果你需要这样做,这意味着这是一个常见的行为。您通常会有以下情况:

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

如果你需要这样做,这意味着这是一个常见的行为。您通常会有以下情况:

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

你不应该有这样的清单。另一个选项是使用(或
.getClass()
)的instanceof,然后是downcast。

您不应该有这样的列表。另一种方法是使用
instanceof
(或
.getClass()
),然后进行向下转换。使用
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()
方法。。。使用
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()
方法。。。您将有一个不同的
列表

,理想情况下,您将对每个可以在基类上声明并在子类中重写的项执行类似的操作(例如
speak()
)。那么你就不必担心类型了。如果按原样进行,那么是的,您需要强制转换以调用该方法。(我有意识地排除了使用反射来调用方法的选项)除非将
bark()
fly()
移动到超类
Animal
,否则无法避免。理想情况下,对于可以在基类上声明并在子类中重写的每个项,都可以执行类似的操作(例如
speak()
)。那么你就不必担心类型了。如果按原样进行,那么是的,您需要强制转换以调用该方法。(我有意识地排除了使用反射调用方法的选项)除非将
bark()
fly()
移动到超级类
Animal
,否则您无法避免。您是说将它们分为2个列表吗?您是说将它们分为2个列表吗?