【问题标题】:In an ArrayList of Object, how can I convert Object into one of 3 instance of classes contained in an ArrayList?在 Object 的 ArrayList 中,如何将 Object 转换为 ArrayList 中包含的 3 个类实例之一?
【发布时间】:2023-04-03 22:49:01
【问题描述】:

我正在做一个简单的 Zoo 应用程序来理解 Java 中的面向对象概念。

我的模型如下: 1) 一个动物园有许多笼子 2) 笼子里有猫科动物、灵长类动物或鸟类的混合物 3)动物可以吃,睡或喝 4)猫扩展动物(做额外的猫的东西) 5)灵长类动物扩展动物(做额外的灵长类动物的东西) 6) 鸟扩展动物(做额外的鸟的东西)

问题:

虽然在动物园中处理 x 个笼子(笼子的数组列表)非常容易,但我在处理笼子里的动物时遇到了困难。 我发现我需要一个对象的 ArrayList。

到目前为止一切都很好,但是当我试图找回我的动物并让他抓一个帖子时,它不再是猫科动物,而是一个物体。

public class Cage{

        private String name;
        private ArrayList<Object> animals = new ArrayList<Object>();

        public Cage(String name){
            this.name = name;
        }

        public void addFeline(String name){
            Feline newFeline= new Feline(name);
            this.animals.add(newFeline);
        }

        public void addPrimate(String name){
            Primate newPrimate= new Primate(name);
            this.animals.add(newPrimate);
        }

        public void addBird(String name){
            Bird newBird= new Bird(name);
            this.animals.add(newBird);
        }

        public void removeAnimal(int index){
            this.animals.remove(index);
        }

        public Object getAnimal(int index){
            Object myAnimal = this.animals.get(index);
            return myAnimal;
        }
    }

还有我的称呼:

Zoo myZoo = new Zoo("My Zoo");
myZoo.addCage("Monkey Exhibit");
Cage myCage = myZoo.getCage(0);
myCage.addFeline("Leo");
Object MyAnimal = myCage.getAnimal(0);

问题:如何将 Object 转回 Feline 类的实例,以便它可以 Scratch a Post?

【问题讨论】:

  • 转换或转换?它有所作为。

标签: java object arraylist


【解决方案1】:

我认为解决这个问题的最佳方法是使用策略设计模式。

Feline、Primate 和 Bird 应该实现接口 Animal。然后笼子会有一个方法 public void addAnimal(Animal animal);

Feline、Primate 和 Bird 的对象创建应在 Cage 之外。

如果有帮助的话,我已经整理了一些代码。我会设计类似于下面的应用程序。

应使用接口封装行为。例如饮食行为

public interface Animal {
    public String getName();
}
public interface EatingBehaviour {
    public void howManyTimes();
}

public class RealLionEatingBehaviour implements EatingBehaviour{
    @Override
    public void howManyTimes() {
        System.out.println("I eat once a day");
    }
}

public class ToyLionEatingBehaviour implements EatingBehaviour {
    @Override
    public void howManyTimes() {
        System.out.println("I never eat! I am a toy lion.");
    }
}

public abstract class Feline implements Animal{
    public abstract void scratchPost();
    private EatingBehaviour eatingBehaviour;
    public EatingBehaviour getEatingBehaviour() {
        return eatingBehaviour;
    }
    public void setEatingBehaviour(EatingBehaviour eatingBehaviour) {
        this.eatingBehaviour = eatingBehaviour;
    }
}

public class Lion extends Feline {
    private String name;
    public String getName() {
        return this.name; 
    }
    public void setName(String name) {
        this.name = name; 
    }
    Lion (String name) {
        this.name=name;
    }
    public void scratchPost(){
        System.out.println(getName() + " Lion Scratching Post!");
    }   
}

public class AnimalFactory {
    public static Animal getAnimalInstance(String type, String name){
        Animal animal=null;
        if ("lion".equalsIgnoreCase(type)) {
            animal = new Lion(name);
        }
        return animal;
    }
}

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

public class Cage {
    private List<Animal> animals = new ArrayList<Animal>();
    public void addAnimal(Animal animal) {
        animals.add(animal);
    }
    public void removeAnimal(int index){
        this.animals.remove(index);
    }
    public Animal getAnimal(int index){
        return this.animals.get(index);
    }   
}

public class Zoo {
    public static void main(String args[]) {
        Cage cage = new Cage();
        Animal animal = null;
        animal = AnimalFactory.getAnimalInstance("Lion", "Sweety");
        cage.addAnimal(animal);
        Animal animalFromCage = cage.getAnimal(0);
        if (animalFromCage instanceof Feline) {
            Feline feline = (Feline) animalFromCage;
            feline.setEatingBehaviour(new RealLionEatingBehaviour());
            feline.scratchPost();
            feline.getEatingBehaviour().howManyTimes();
            feline.setEatingBehaviour(new ToyLionEatingBehaviour());
            feline.getEatingBehaviour().howManyTimes();
        }
    }
} 

【讨论】:

  • 那么每次我们添加具有更多不同行为的动物时,您是否需要调整界面?
  • 这就是我理解的实际情况。这是否意味着我的动物类已经消失了,或者接口动物实现了动物类?哦'
  • 如果我们考虑设计一个包含整个动物王国的应用程序,那么 Animal 可能是根接口。目前我可以想到有一个接口层次结构的大树。即使是猫科动物也不能是完全实现的类。狮子会。我认为正确使用策略设计模式将是答案。
  • 在你的例子中,如果动物现在是一个接口而不是一个类,你会将所有动物共有的吃、睡和喝等方法放在哪里?
  • 变量名将属于每个类而不是超类动物。如果我的动物有更多的属性,比如疲劳、饥饿、攻击性,那么为它设置一个界面还有意义吗?我至少需要能够设置这些值。你认为它们应该在每个专门的动物类别中复制吗?
【解决方案2】:

使用演员表:

Object myAnimal = myCage.getAnimal(0);
Feline f = (Feline) myAnimal;

【讨论】:

  • 感谢您的超级快速回答。如果事实上这个类不是猫科动物会发生什么?是否有与此相关的最佳实践?
  • 当然,这假设你知道位置 0 的动物是Feline
  • 然后会抛出一个ClassCastException。这里的最佳实践:列出Animal 接口,并让所有具体的动物实现它。使用多态性让每只动物做出适当的动作。
  • 请注意,创建具有不同具体类型的Object 列表不是一个好主意,这最终会导致问题,而且这是一种设计味道。最好确保列表中的所有元素都是同一类型,如上一条评论中所建议的那样
  • 我会研究接口。我想正确地做到这一点。没有捷径。
【解决方案3】:
private List<Animal> animals = new ArrayList<Animal>();
    public void findAnimal(int index) {
        Animal myAnimal = animals.get(index);
        if (myAnimal instanceof Feline) {
            Feline feline = (Feline) myAnimal;
            //do the work with Feline
        } else if (myAnimal instanceof Primate) {
            //do the work with Primate
        }
        // continue with the other types.
    }

这将避免意外的类转换异常。由于您知道类型,因此在 Arraylist 中使用超类型(动物)而不是对象。如果是 Obejct,您可以将任何内容添加到列表中。

【讨论】:

  • 这毫无意义。如果Animal 是返回类型,那么检查并转换为Feline 等有什么意义?
【解决方案4】:

您应该使用ArrayList&lt;? extends Animal&gt; 而不是ArrayList&lt;Object&gt;。然后将返回值强制转换为 Animal 的适当子类。

【讨论】:

  • 这并不比使用Object 作为基类好多少。
  • 你能举一个例子说明它是如何应用的,因为当我将对象更改为 extends Animal>,addFeline、addPrimate 和 addBird 方法以“?Capture in Animal 不能应用于 Feline”开始失败
  • 试试Animal 而不是? extends Animal
猜你喜欢
  • 2014-05-09
  • 1970-01-01
  • 2012-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-17
  • 1970-01-01
相关资源
最近更新 更多