0

I have the following classes:

Class Dog extends Animal
Class Cat extends Animal
Class Mouse extends Animal

Furthermore, I have a List in which I put every Animal, regardless of the subclass:

List<? extends Animal> list = new ArrayList<? extends Animal>();

Populating said list with Dogs, Cats and Mice works perfectly, unless I want to later check what kind of Animal there is inside the list.

for (Animal animal: list) {
    if (animal instanceof Dog) {
        //do some dog stuff
    }
    if (animal instanceof Cat) {
        // do some cat stuff
    }    
}

How can I check for each Animal in the list whether it is a Dog, a Cat or a Mouse?

Saro Taşciyan
  • 5,210
  • 5
  • 31
  • 50
Calius
  • 9
  • 1
  • 3
    You should use polymorphism (i.e. overridden methods) to avoid having to do `instanceof` checks. – Oliver Charlesworth Feb 09 '14 at 23:37
  • What kind of "check" do you want? Are you wanting the class or are you comfortable with a String? – Makoto Feb 09 '14 at 23:39
  • I would like to know which kind of animal I am currently working with, so that I can run a specific code for each animal, i.e. Dog, Cat and Mouse. I think I want to know the class. – Calius Feb 09 '14 at 23:41
  • Are you sure it needs to be specific to an individual animal and *not* achievable as Oli Charlesworth suggests? – ChiefTwoPencils Feb 09 '14 at 23:42
  • Maybe if you shared with us what it is you're doing with in each `instanceof` check, then we could give you a better (read: polymorphic) answer. – Makoto Feb 09 '14 at 23:43
  • 1
    Just as a style thing, I believe this syntax: `List list = new ArrayList();` is equivalent, and certainly much nicer. – Azar Feb 09 '14 at 23:46
  • The list contains all animals which have been parsed from an XML file. All I want to do next is put every animal into the right animal_table. For instance: [pseudocode] if (animal instanceof Dog){ //run isertIntoDogTableMethod} – Calius Feb 09 '14 at 23:46
  • @Azar: If you have intentions on modifying the list, then that form would be acceptable. If you *don't* want to modify the list, then `? extends Animal` is appropriate. – Makoto Feb 09 '14 at 23:49
  • @Makoto [I suppose you learn something every day.](http://stackoverflow.com/questions/2575363/generics-list-extends-animal-is-same-as-listanimal) – Azar Feb 09 '14 at 23:53
  • If you can change these classes, just go there and implement whatever you want there. Sometimes, you can do that: https://sites.google.com/site/steveyegge2/when-polymorphism-fails – rdllopes Feb 09 '14 at 23:57
  • Ok, thanks for your help! I will go the polymorphic way. It seems straightforward enough ;-) – Calius Feb 09 '14 at 23:58
  • "Populating said list with Dogs, Cats and Mice works perfectly" No it doesn't. How would you populate it? – newacct Feb 10 '14 at 08:23

2 Answers2

0

If you want to avoid multiple instanceof checks, you could have Dog, Cat and Mouse derive from the common superclass Mammal (which itself would be a subclass of Animal). Then you only have to check:

if (animal instanceof Mammal) { }

A cleaner solution would be to move the processing into a method, which you override for each type of Animal:

abstract class Animal
{
    public abstract void feed ();
}

class Dog extends Animal
{
    public void feed()
    {
        // feed the dog
    }
}

Saro Taşciyan
  • 5,210
  • 5
  • 31
  • 50
Tony the Pony
  • 40,327
  • 71
  • 187
  • 281
  • wonderful. i would tag that answer as code-trolling if answers could be tagged :) – luksch Feb 09 '14 at 23:43
  • whoops... i guess now the answer got a second part that actually deals with the OPs promlem.. . Sorry to have misinterpreted your first attempt. – luksch Feb 09 '14 at 23:45
0

Wildcards such as <? extends Animal> are useful when your list contains elements of a derived type (i.e. Cat/Dog etc), but you don't know or care what it is. They're made so that they match ArrayList<Dog> or ArrayList<Cat> etc when you work with them in a generic way in methods.

But since you seem to be adding all kinds of elements into your list, you're very well off with ArrayList <Animal> in which you could add Dogs, Cats or what have you, because they are derived from Animal and therefore they are Animals.

Instead of the instanceof checks, I'd recommend adding a polymorphic method in the superclass and overriding it in all subclasses, so that you could later call it without needing to care what type the actual object is.

webuster
  • 2,490
  • 18
  • 27