通过超类对象的ArrayList访问子类方法?

时间:2015-10-18 04:09:06

标签: java inheritance arraylist polymorphism

我有一个超类(Animal)和两个子类(Frog和Lion)。在我下面的私人方法中,我创建了三个狮子会和一个青蛙。我在第一个循环中显示Animal的所有四个重量,在第二个循环中显示所有Lion的名字。我得到了正确的输出,但我的老师告诉我"不需要在main方法中创建两个ArrayLists。"我猜他建议我使用我的第一个ArrayList来访问我的Lion子类的getName()方法。

这就是我这样做的方式,它起作用了:

 import java.util.ArrayList;

    public class AnimalTest {

        public static void main(String[] args){
            ArrayList<Animal> animalList = createList();

            for(int i = 0; i < animalList.size(); i++){
                System.out.println(animalList.get(i).getWeight() + " lbs");
            } 

            ArrayList<Lion> lionList = createList();
            for(int j = 0; j < 3; j++){
                System.out.println(lionList.get(j).getName());
            }

        }

        private static ArrayList createList(){
            ArrayList<Animal> list = new ArrayList<Animal>();

            list.add(new Lion("Leo I", 530.00));
            list.add(new Lion("Leo II", 560.00));
            list.add(new Lion("Leo III", 590.00));
            list.add(new Frog("Freddie", 7.00));

            return list;
        }

    }

他是否希望我通过相同的ArrayList列表从我的Lion类访问我的getName()函数?我想我可以通过一些演员来做到这一点,如下:

//ArrayList<Lion> lionList = createList();
for(int j = 0; j < 3; j++){
   System.out.println(animalList.(Lion)get(j).getName());
}

但是这不起作用..我不明白我应该如何在不创建另一个ArrayList的情况下使用我的Lion子类的getName()方法。

以下是我的其他课程:

public class Animal {
    private String genus;
    private String species;
    private double weight;
    private boolean tail;

    public Animal(){}

    public Animal(String genus, String species){
        this.genus = genus;
        this.species = species;
    }

    public String getGenus(){
        return genus;
    }

    public String getSpecies(){
        return species;
    }

    public double getWeight(){
        return weight;
    }

    public void setWeight(double weight){
        this.weight = weight;
    }

    public boolean hasTail(){
        return tail;
    }

    public void setTail(boolean tail){
        this.tail = tail;
    }

}


public class Lion extends Animal {
    private String name;

    public Lion(){}

    public Lion(String name, double weight){
        super("Panthera", "Leo");
        this.name = name;
        setWeight(weight);
        setTail(true);
    }

    public String getName(){
        return name;
    }
}


public class Frog extends Animal {
    private String name;

    public Frog(){}

    public Frog(String name, double weight){
        super("Lithobates", "Catesbeianus");
        this.name = name;
        setWeight(weight);
        setTail(false);
    }

    public String getName(){
        return name;
    }
}

3 个答案:

答案 0 :(得分:1)

您的createList函数返回raw-type,不要这样做。另外,我建议您编程到界面。但是您的第二个示例lionList似乎需要createLionList方法。像,

private static List<Lion> createLionList() {
    List<Lion> list = new ArrayList<>();
    list.add(new Lion("Leo I", 530.00));
    list.add(new Lion("Leo II", 560.00));
    list.add(new Lion("Leo III", 590.00));
    return list;
}

然后我们可以修改第一个createList来添加它。像,

private static List<Animal> createList() {
    List<Animal> list = new ArrayList<>();
    list.addAll(createLionList());
    list.add(new Frog("Freddie", 7.00));
    return list;
}

main方法中,我更喜欢for-each loop。并且formatted output。像,

List<Animal> animalList = createList();
for (Animal a : animalList) {
    System.out.printf("Weight: %d lbs, Name: %s", a.getWeight(),
            a.getName());
}

答案 1 :(得分:0)

你有正确的想法,你刚刚得到了错误的演员语法。尝试:

((Lion)animalList.get(j)).getName()

虽然如果青蛙和狮子都有名字,那么将getName()放在Animal课程中会更有意义。

答案 2 :(得分:0)

父类无法访问子类的字段或方法,因为它不知道它实现了什么。

考虑到这一点,合乎逻辑的做法是将您需要访问的内容放在Animal类中。这意味着您要将name字段提升到父Animal类,然后在那里访问它。

然后,您只需要一个ArrayList

ArrayList<Animal> animalList = createList();
for(Animal animal : animalList) {
    System.out.println(animal.getWeight());
    System.out.println(animal.getName());
}

此外,您需要对createList方法进行两次 非常重要的 更改:

  • 不要返回原始ArrayList。永远。您需要正确输入。

    public ArrayList<Animal> createList() { }
    
  • 您不应该关心它是ArrayList还是List。最好(尽管不是必需的)编程到List的界面。

    public List<Animal> createList() { }
    

    对于奖励积分,您可以通过使其不可变或使用PECS来阻止列表的突变:

    public List<? extends Animal> createList() { }