如何为ArrayList中的所有对象调用方法?

时间:2017-04-08 23:27:21

标签: java arraylist

所以我有一个界面Pet如下所示:

public interface Pet{
    void Eat();
}

由以下人员实施:

public class Puppies implements Pet {
    @Override
    public void Eat() {
        // Something gets eaten here, presumably
    }
}

public class Kittens implements Pet {
    @Override
    public void Eat() {
        // Everybody knows Kittens eats something different
    }
}

希望我接下来要做的是创建ArrayList新宠物:

public class PetList{

    public PetList(){
        ArrayList pets = new ArrayList<Pet>();

        Puppies spot = new Puppies();
        Puppies rex = new Puppies();
        Kittens meowth = new Kittens();

        pets.add(spot);
        pets.add(rex);
        pets.add(meowth);
    }

public static void main(String[] args){
    // No idea how to handle this bit
}

接下来我要做的就是告诉我所有的宠物吃。我该怎么做?

5 个答案:

答案 0 :(得分:7)

您当前代码的主要问题是ArrayListpets PetList构造函数是本地的,这意味着您不能访问类PetList的构造函数外部。

首先,将ArrayList作为PetList类的实例变量,以便通过对象可以访问,甚至在构造函数之外

然后,您可以提供eatAll()方法,该方法会迭代ArrayList<Pet>并在所有eat()个对象上调用pet方法。

您可以参考以下代码并按照内联评论:

public class PetList{
    private List<Pet> pets;//now this is an instance variable

    public PetList(){
        this.pets = new ArrayList<Pet>();//this list is not local now
        Puppies spot = new Puppies();
        Puppies rex = new Puppies();
        Kittens meowth = new Kittens();
        pets.add(spot);
        pets.add(rex);
        pets.add(meowth);
    }

    public void eatAll() { //method to invoke eat() on list of pets
        for(Pet pet : this.pets) { //iterate the pets list
            pet.eat();//call eat() on each pet object
        }
    }

    public static void main(String[] args){
          PetList petList = new PetList();
          petList.eatAll();//invoke the eatAll() method
     }
}

作为旁注,我强烈建议您遵循Java 命名标准Eat()应为eat(),即方法名称应以小写开头)并考虑PetList类重命名为PetsTesting (或其他内容),以便开发人员更直观。

最后,但重要的一点是,不要将对象直接分配给具体类类型,如ArrayList<Pet> pets = new ArrayList<>();Puppies spot = new Puppies();

最佳做法是,您需要将对象分配给接口类型List<Pet> pets = new ArrayList<Pet>();Pet spot = new Puppies();(对于接口类型称为代码

答案 1 :(得分:6)

public static void main(String[] args){
    pets.foreach(pet::eat);
}

应该让他们都吃完

答案 2 :(得分:3)

  

由以下人员实施:

您实际上必须实现接口,仅在具体类中定义方法是不够的。在这里你是如何做到的:

public class Kittens implements Pet {}

由于您有一个界面,请让您的实例类型为Pet类型,而不是

Puppies spot = new Puppies();

那将是

  

Pet spot = new Puppies();

我建议学习/继续学习java基础知识(继承,多态和其他概念)。

以下是您需要的工作方式:

  

Pet.java

public interface Pet {
    void eat();
}
  

Kettens.java

public class Kittens implements Pet {
    @Override
    public void eat() {
        System.out.println("Everybody knows Kittens eats something different");
    }
}
  

Puppies.java

public class Puppies implements Pet {
    @Override
    public void eat() {
        System.out.println("Something gets eaten here, presumably");
    }
}
  

PetList.java

import java.util.ArrayList;
import java.util.List;

public class PetList {
    public static void main(String[] args) {
        Pet spot = new Puppies();
        Pet rex = new Puppies();
        Pet meowth = new Kittens();

        List<Pet> pets = new ArrayList<>();
        pets.add(spot);
        pets.add(rex);
        pets.add(meowth);

        PetList.feadPets(pets);
    }

    public static void feadPets(List<Pet> pets) {
        for (Pet p : pets) {
            p.eat();
        }
        // Java 8 / Stream syntax.
        // pets.forEach(Pet::eat);
    }
}

答案 3 :(得分:2)

您当前方法的问题仅将ArrayList pets限制为构造函数,因此main无法访问它。

这就是你解决这个问题的方法

public class PetList {

    List<Pet> pets; // should be private, though

    public PetList() {
        this.pets = new ArrayList<Pet>();
    }

在主要

// Should be using a getter, though
for (Pet pet : new PetList().pets) {
    pet.eat();
}

其他建议

1)创建一些List<Pet>(或者让你的整个班级成为一个列表)
2)迭代它,并调用共享接口的方法

public class PetList extends ArrayList<Pet> {

    public PetList() {
        add(new Puppy());
        add(new Kitten());
    }

    public static void main(String[] args) {
        PetList pets = new PetList();

        for (Pet pet : pets) {
            pet.eat();
        }
    }
}

答案 4 :(得分:1)

javaguy已经提供了您可能一直在寻找的答案,但由于您似乎对该主题不熟悉,因此以下是对您的代码的更多建议:

如果您希望java将Puppies类识别为Pet接口的实现,则必须在类定义中明确说明:

public class Puppies implements Pet

PetList课程中,您在所谓的构造函数中初始化(即创建)列表和宠物变量。这意味着除非您创建此类的对象,否则这些变量是不可访问的。您可能希望找到有关如何处理实例化类的指南。现在我建议使用以下解决方案:不是编写子类并在那里初始化变量,而是在main方法中执行:

import java.util.ArrayList;
public class PetList{
    public static void main(String[] args){

        //Initialize the pet list
        ArrayList pets = new ArrayList<Pet>();
        Puppies spot = new Puppies();
        Puppies rex = new Puppies();
        Kittens meowth = new Kittens();
        pets.add(spot);
        pets.add(rex);
        pets.add(meowth);

为了喂养动物,您可以使用 for-each-loop 遍历列表。 (你也应该看一下这个)

        //Feed the animals
        for(Pet p: pets){
            System.out.println("Serving a meal.")
            p.Eat();
        }

[请同时阅读下面样式指南中的最后一点,因为此代码无法编译。]快速介绍:此构造迭代,即遍历{{1}中的所有元素变量并将它们一次一个地存储在局部变量pets中。在括号内,您可以对此变量执行任何操作,在这种情况下,在其上调用p方法。如果您添加Eat()并在动物'System.out.…方法中添加Eat()

,请查看控制台输出的内容

由于您在此处使用System.out.println("Kittens just ate.");,您还可以通过索引访问各个宠物,即列表中的位置。使用 for-loop

ArrayList

快速风格指南

  • 班级名称应采用单数形式,例如: //Feed the animals once more for(int i=0; i<pets.size(); i++){ // For each i which is greater or equal to zero and less than the size of pets, pets.get(i).Eat(); //Feed the animal in the i-th position in pets } 代替Puppy
  • 方法名称不应大写,例如Puppies代替eat()
  • 您可以告诉Eat()(以及大多数其他容器)您将提供哪种数据。这提高了类型安全性,因为它可以检查错误,如果您运行代码并且崩溃,那么其他错误只会是明显的。

假设您有另一个树类:ArrayList正如您的代码现在一样,这是可能的,但崩溃:

public class Tree { /* No Eat() method! */}

但是,如果您将Tree tree = new Tree(); pets.add(tree); for(Pet p: pets){ p.Eat(); // Will crash if p reaches the tree. } 像这样

进行参数化
petList

Java可以将树检测为添加到宠物列表中的奇怪之处。 (实际上,Java也不会编译第一个实例,但我认为这是一种很好的类型安全方法。)