所以我有一个界面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
}
接下来我要做的就是告诉我所有的宠物吃。我该怎么做?
答案 0 :(得分:7)
您当前代码的主要问题是ArrayList
(pets
) 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也不会编译第一个实例,但我认为这是一种很好的类型安全方法。)