Variance is another aspect related to parameterized types. To understand why it is needed and how it works, let's have a drink. First, we will define a glass that can be (half) full or empty:

sealed trait Glass[Contents]case class Full[Contents](contents: Contents) extends Glass[Contents]case object Empty extends Glass[Nothing]

There can only be one empty glass filled with Nothing, and we model this case with a case object. A full glass can be filled with different contents. Nothing is a subclass of any class in Scala, so in our case it should be able to substitute any contents. We will now create the contents and we would like to be able to drink it. The implementation is not important in this case:

case class Water(purity: Int) ...

Get Learn Scala Programming now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.