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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15995540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 21:35:27  来源:igfitidea点击:

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

javamethodsarraylistsubclasssuperclass

提问by whiteElephant

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 Birdflies when move()is called. I know I can access common methods and properties of the super class by using this

它们都实现了一个方法move()- The Birdflies whenmove()被调用。我知道我可以通过使用这个来访问超类的常用方法和属性

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 Birdhas. I could do this by casting the Animalas a Bird:

很好 - 但现在我想访问move()子类Bird拥有的方法。我可以通过将Animala转换为 a来做到这一点Bird

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?

好像有点多余,有没有更好的办法?

回答by Makoto

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 movemethod, change Animalfrom a superclass to an interface. Then when you call the movemethod, you'll be able to ensure that you're calling the appropriate move method for the object you want.

为确保您实际调用了适当的move方法,请Animal将超类更改为接口。然后,当您调用该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 Animalinterface.

如果您希望保留公共字段,那么您可以定义一个抽象类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();
}

回答by Lokesh

You dont need to do any casting. The overridden method should get called [simple polymorphism]

你不需要做任何铸造。重写的方法应该被调用 [简单多态]

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

Above code should call bird method if object is of bird, isn't it?

如果对象是鸟,上面的代码应该调用鸟方法,不是吗?

And casting is not a solution , how will you decide which object to cast? You will have to use instanceOf.

并且投射不是解决方案,您将如何决定投射哪个对象?您将不得不使用 instanceOf。

回答by BlackJoker

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

回答by Bhushankumar Lilapara

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();