2015-10-18 87 views
1

我有一个超类(动物)和两个子类(青蛙和狮子)。在我下面的私人方法中,我创建了三个狮子和一个青蛙。我在第一个循环中显示动物的所有四个重量,并在第二个循环中显示所有狮子的名字。我得到正确的输出,但是我的老师告诉我“在主方法中不需要创建两个ArrayLists”。我猜他建议我使用我的第一个ArrayList来访问我的Lion子类的getName()方法。通过超类对象的ArrayList访问子类方法?

这是我做到了,这是工作:

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列表访问我的getName()函数?我想我可以做一些铸造做到这一点,就像这样:

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

但是,这并不工作..我不明白,我也应该去我的狮子子类的getName()方法,而不创建另一个的ArrayList ..

这里是我班的其余部分:

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; 
    } 
} 
+0

做青蛙也有名称(如“弗雷迪青蛙”) ?也许也是'getName()'方法?你的老师可能会建议你将'getName()'方法移到'Animal'类。 –

+0

是的青蛙也有一个getName()方法。该指令明确表示,在动物类中没有关于动物名称的任何内容,但是.. – JakeFromStateFarm

回答

1

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

考虑到这一点,合乎逻辑的做法是将您需要访问的内容放在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() { } 
    
  • 你不应该关心它作为一个ArrayListList。相反,编程到List的界面是可取的(但不是必需的)。

    public List<Animal> createList() { } 
    

    奖励积分,你可以阻止列表中的突变或者通过使其不变或使用PECS:

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

@JakeFromStateFarm,所以,这个任务没有说明你不能在Animal类中引用任何名字?引用你的评论:“......这些指令明确表示在Animal类中没有关于动物名称的任何内容,但是..” – nihilon

+0

@nihilon正确,该作业只提到在特定动物的子类中添加该名称。虽然我看不到他希望我怎么做,但我已经尝试过铸造和一切。老实说,我认为他没有意识到他自己的指示说了什么,哈哈。我认为Makoto是对的,父类并不真正了解子类的字段或方法。周一我要亲自去问我的导师。他在线给我发了这条消息,内容非常模糊。 – JakeFromStateFarm

+1

除非他希望你使用一个接口,那就是。但是那会有点愚蠢,因为你已经*有一个共同的对象来引用。 – Makoto

0

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

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

尽管如果两个青蛙和狮子可以有名字,那就更有意义,只是把getName()Animal类。

+1

这似乎是正确的,但它也不能正常工作..它说它无法在Animal类中找到getName()。它应该在狮子类而不是在这个铸造动物类看,虽然,对吗? – JakeFromStateFarm

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

你的意思是我的方法签名应该是ArrayList 返回类型而不是仅仅ArrayList?使用“List”而不是“ArrayList”是一回事吗?另外,感谢您使用foreach循环的想法,这是有道理的,因为我只是打印所有的动物而不是几个选择。 – JakeFromStateFarm

+1

@JakeFromStateFarm实质上就是他的意思。但是使用'List'作为返回类型而不是'ArrayList'意味着你可以在稍后修改'ArrayList'到'LinkedList'或者'List'的其他一些实现,并且对代码的其余部分进行最小的修改是必要的。这不直接相关,而是一个免费的提示。 – nihilon

+0

噢,好的。我想我们还没有涉及到“列表”,只是ArrayList .. – JakeFromStateFarm