Search code examples
javagenericssolid-principlesliskov-substitution-principle

Doesn't Java Generics upper bound rule breaks Liskov substitution?


I was reading about Java Generics and following part seemed problematic:

public class Farm {
  private List<Animal> animals;

  public void addAnimals(Collection<Animal> newAnimals) {
    animals.addAll(newAnimals);
  }
}

farm.addAnimals(cats); // Compilation error
farm.addAnimals(dogs); // Compilation error

Cat and Dog are subclasses of Animal.

In order to make it work it is required to define a wildcard type with an upper bound:

public void addAnimals(Collection<? extends Animal> newAnimals)

Shouldn't I be able to use subclasses and superclasses interchangeably without needing to set an upper bound according to the definition of Liskov substition:

Substitutability is a principle in object-oriented programming stating that an object (such as a class) and a sub-object (such as a class that extends the first class) must be interchangeable without breaking the program.


Solution

  • A collection of only cats is not a subclass of a collection of any animal.

    This and the compilation error are good things. Otherwise, you could declare a collection of only cats, and stick a dog in it. Trouble would ensue.