Search code examples
javapolymorphism

How to downcast List<A> to List<B> when we know List<A> contains only B


Lets say I know for certain that a list contains only elements of type B which extends A. Here is an example representing my situation:

public static class Animal {
    public void feed() {}
}
public static class Cat extends Animal {
}
public static class Zoo {
    public List<Animal> m_animals;
    
    public Zoo() {
        m_animals = new ArrayList<Animal>();
    }
    public void feedAnimals() {
        for(Animal animal : m_animals)
            animal.feed();
    }
}
public static class CatZoo extends Zoo {
    public void addCat(Cat cat) {
        m_animals.add(cat);
    }
    List<Cat> getCats() {
        List<Cat> cats = new ArrayList<Cat>();
        for(Animal cat : m_animals)
            cats.add((Cat) cat);
        return cats;
    }
}

I feel like I'm doing something wrong but I can't quite put my finger on it. CatZoo is still a Zoo and I need the Zoo methods. Cat is definitely an Animal and I need the Animal methods. Anybody who deals with CatZoo should only deal with Cat and not Animal. But getCats() becomes super inefficient. Is there a better way to do this?


Solution

  • I think what you're looking for is a generic Zoo. That way you can move common logic to the base class while letting the subclasses know what type they're working with:

    public static class Zoo<A extends Animal> {
        public List<A> m_animals;
    
        public void add(A animal) {
            m_animals.add(animal);
        }
    }
    
    public static class CatZoo extends Zoo<Cat> {
        public void meow() {
            for (Cat cat : m_animals)
                cat.meow();
        }
    }