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

Hi, I am wondering if there is a simple solution to my problem,

I have an 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 the move() method - Bird flies when move() called. I know that I can access the general methods and properties of a superclass using this

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

This is good - but now I would like to access the move() method, which has a subclass of Bird . I could do this by typing Animal as Bird :

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

In my situation, I do not want to do this, as this will mean that I have 3 different sets of code above for each subtype of Animal .

Seems a little redundant, is there a better way?

+6
source share
4 answers

There is really no good way to do this from a superclass, as the behavior of each subclass will be different.

To make sure that you actually call the appropriate move method, change Animal to a superclass on the interface. Then, when you call the move method, you can make sure that you call the appropriate move method for the desired object.

If you want to keep common fields, then you can define an abstract AnimalBase class and require all animals to handle it, but each implementation will have to implement the Animal interface.

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

You do not need to do a casting. Overridden method should be called [simple polymorphism]

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

The above code should call the bird method if the object has a bird, right?

And casting is not a decision, how do you decide which object to cast? You will need to use instanceOf.

+1
source

In your case, the following may work, but the time complexity is O (n):

 public void moveBird(){ for(Animal aminal:animalList){ if(animal instanceof Bird){ aninmal.move(); } } } 
0
source
 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(); 
-1
source

All Articles