What\'s the difference between
[A <: B]
and
[+B]
in Scala?
I would like to extend Rex Kerr's excellent answer with some more examples: Let's say we have four classes:
class Animal {}
class Dog extends Animal {}
class Car {}
class SportsCar extends Car {}
case class List[+B](elements: B*) {} // simplification; covariance like in original List
val animals: List[Animal] = List( new Dog(), new Animal() )
val cars: List[Car] = List ( new Car(), new SportsCar() )
As you can see List does not care whether it contains Animals or Cars. The developers of List did not enforce that e.g. only Cars can go inside Lists.
Additionally:
case class Shelter(animals: List[Animal]) {}
val animalShelter: Shelter = Shelter( List(new Animal()): List[Animal] )
val dogShelter: Shelter = Shelter( List(new Dog()): List[Dog] )
If a function expects a List[Animal]
parameter you can also pass a List[Dog]
as an argument to the function instead. List[Dog]
is considered a subclass of List[Animal]
due to the covariance of List. It would not work if List was invariant.
case class Barn[A <: Animal](animals: A*) {}
val animalBarn: Barn[Animal] = Barn( new Dog(), new Animal() )
val carBarn = Barn( new SportsCar() )
/*
error: inferred type arguments [SportsCar] do not conform to method apply's type parameter bounds [A <: Animal]
val carBarn = Barn(new SportsCar())
^
*/
As you can see Barn is a collection only intended for Animals. No cars allowed in here.