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]
andBox[Hammer]
independently of the subtyping relationship ofTool
andHammer