简体   繁体   English

ArrayList包含同一个超类的不同对象 - 如何访问子类的方法

[英]ArrayList containing different objects of the same superclass - how to access method of a subclass

Hi I'm wondering if there is a simple solution to my problem, 嗨,我想知道我的问题是否有一个简单的解决方案,

I have an ArrayList : 我有一个ArrayList

ArrayList <Animal> animalList = new ArrayList<Animal>(); 

/* I add some objects from subclasses of Animal */

animalList.add(new Reptile());
animalList.add(new Bird());
animalList.add(new Amphibian());

They all implement a method move() - The Bird flies when move() is called. 它们都实现了一个方法move() - 当调用move()时, Bird会飞。 I know I can access common methods and properties of the super class by using this 我知道我可以通过使用它来访问超类的常用方法和属性

public void feed(Integer animalIndex) {
    Animal aAnimal = (Animal) this.animalList.get(animalIndex);
    aAnimal.eat();
}

That's fine - but now I would like to access the move() method the subclass Bird has. 那没关系 - 但现在我想访问子类Bird具有的move()方法。 I could do this by casting the Animal as a Bird : 我可以通过将AnimalBird一样投射来做到这一点:

Bird aBird = (Bird) this.animalList.get(animalIndex);
aBird.move();

In my situation I don't want to do this, as it will mean I have 3 different sets of the above code one for each subtype of Animal . 在我的情况下,我不想这样做,因为这意味着我有3个不同的上述代码集,每个子​​类型为Animal

It seems a bit redundant, is there a better way? 这似乎有点多余,有更好的方法吗?

There really isn't a nice way to do this from the superclass, since the behavior of each subclass will be different. 从超类中确实没有很好的方法可以做到这一点,因为每个子类的行为都会有所不同。

To ensure that you're actually calling the appropriate move method, change Animal from a superclass to an interface. 要确保您实际调用适当的move方法, move Animal从超类更改为接口。 Then when you call the move method, you'll be able to ensure that you're calling the appropriate move method for the object you want. 然后,当您调用move方法时,您将能够确保为所需对象调用适当的移动方法。

If you're looking to preserve common fields, then you can define an abstract class AnimalBase , and require all animals to build off of that, but each implementation will need to implement the Animal interface. 如果你想保留公共字段,那么你可以定义一个抽象类AnimalBase ,并要求所有动物构建它,但每个实现都需要实现Animal接口。

Example: 例:

public abstract class AnimalBase {
    private String name;
    private int age;
    private boolean gender;

    // getters and setters for the above are good to have here
}

public interface Animal {
    public void move();
    public void eat();
    public void sleep();
}

// The below won't compile because the contract for the interface changed.
// You'll have to implement eat and sleep for each object.

public class Reptiles extends AnimalBase implements Animal {
    public void move() {
        System.out.println("Slither!");
    }
}

public class Birds extends AnimalBase implements Animal {
    public void move() {
        System.out.println("Flap flap!");
    }
}

public class Amphibians extends AnimalBase implements Animal {
    public void move() {
        System.out.println("Some sort of moving sound...");
    }
}

// in some method, you'll be calling the below

List<Animal> animalList = new ArrayList<>();

animalList.add(new Reptiles());
animalList.add(new Amphibians());
animalList.add(new Birds());

// call your method without fear of it being generic

for(Animal a : animalList) {
    a.move();
}

You dont need to do any casting. 你不需要做任何铸造。 The overridden method should get called [simple polymorphism] 被重写的方法应该被称为[simple polymorphism]

Animal aAnimal==  this.animalList.get(animalIndex);
aAnimal.move();

Above code should call bird method if object is of bird, isn't it? 如果对象是鸟,上面的代码应该调用bird方法,不是吗?

And casting is not a solution , how will you decide which object to cast? 而铸造不是解决方案,您将如何决定投射哪个对象? You will have to use instanceOf. 您将不得不使用instanceOf。

In your case,the following could work,but time complexity is O(n): 在您的情况下,以下可能有效,但时间复杂度为O(n):

public void moveBird(){
    for(Animal aminal:animalList){
        if(animal instanceof Bird){
            aninmal.move();
        }
    }
}
Bird getMyBird(Integer aniInteger) {
        Bird b = new Bird();
        //Do somthig with bird object...

        return b;
        //get your modifeid bird object
    }

    Bird myBird = animalList.get(animalIndex);

    myBird.move();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM