Variance provides a way to constrain parameterized types. It defines a subtyping relationship between parameterized types based on the subtyping relationship of their component types.

Imagine that you have the following class hierarchy:

class Tool
class HandTool extends Tool
class PowerTool extends Tool
class Hammer extends HandTool
class Screwdriver extends HandTool
class Driller extends PowerTool
If we define a generic box:
trait Box[T] {
  def get: T

How can Box of Tools relate to one another? Scala provides three ways:

  • Covariant: Box[Hammer] <: Box[Tool] if Hammer <: Tool
  • Contravariant: Box[Tool] <: Box[Hammer] if Tool <: Hammer
  • Invariant: There's no subtyping relationship between Box[Tool] and Box[Hammer] independently of the subtyping ...

Get Professional Scala now with the O’Reilly learning platform.

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