Scala – Covariance

03 Jul, 2020
Variance is the interconnection of Sub-Typing relationships which are either of complicated types or of their constituent types. Scala provides three types of variance:
Covariant
Contravariant
Invariant
Covariance states that if there are two parameterized types such that S is a subtype of T, then List[S] is a subtype of List[T]. This is an inheritance relationship. So, this basically defines the relationship whether we can replace a type by its base type. Simply putting in words, if we take an example where Car is a subtype of Vehicle, then List[Car] is a subtype of List[Vehicle]. Therefore, we can replace List[Car] by List[Vehicle]. When we declare a type to be covariant, then its safe use at various positions becomes limited. In the case of immutable types, covariance is widely used.Syntax:
List[+T]
Here, T is a type parameter and the “+” symbol represents Scala covariance.
Let us discuss this concept with the help of examples:Example 1:
// Scala program to illustrate the concept of covariance  // Creating an abstract class // for Flower abstract class Flower {    def name: String}  // Creating a sub-class Lily // of Flower case class Lily(name: String) extends Flower  // Creating a sub-class Carnation// of Flower case class Carnation(name: String) extends Flower object Covariance extends App{          // Creating a method    def FlowerNames(flowers: List[Flower]): Unit =    {           flowers.foreach         {            flower => println(flower.name)        }    }          // Assigning names    val lily: List[Lily] = List(Lily("White Lily"),                                 Lily("Jersey Lily"))    val carnations: List[Carnation] = List(Carnation("White carnations"),                                           Carnation("Pink carnations"))      // Print: names of lily     FlowerNames(lily)      // Print: names of carnation     FlowerNames(carnations)}
Output:
White Lily
Jersey Lily
White carnations
Pink carnations

Explanation: In the above example, Lily and Carnation are subtypes of Flower. So, it is evident that a List[Lily] is a List[Flower] and a List[Carnation] is also a List[Flower], and we can substitute any of them for a List[Flower]. In the later part of the code, there is a method FlowerNames that prints names of flowers and the acceptable argument is a list of flowers. If the two lists are covariant, only then the method calls will compile and the flower names will get printed respectively. So, as Lily and Carnation are a subtype of Flowers and the last two lines will execute due to covariance.Note:
Abstract class is utilized here to apply covariance as it has List[+T] with it where the type parameter T is covariant.
A trait App is used here to speedily change objects into workable programs.
Example 2:
// Scala program to illustrate the concept of covariance  // Creating an abstract class // for Animalabstract class Animal {    def name: String}  // Creating a sub-class Mammal// of Animal case class Mammal(name: String) extends Animal  // Creating a sub-class Reptile// of Animal case class Reptile(name: String) extends Animal   object CovarianceExample extends App{          // Creating a method    def SpecieNames(animals: List[Animal]): Unit =    {           animals.foreach         {             animal =>println(animal.name)        }    }          // Assigning names    val mammals: List[Mammal] = List(Mammal("Zebra"),                                      Mammal("Horse"))    val reptiles: List[Reptile] = List(Reptile("Snake"),                                        Reptile("Lizard"))      // Print: names of mammals    SpecieNames(mammals)      // Print : names of reptiles    SpecieNames(reptiles)}
Output:
Zebra
Horse
Snake
Lizard

Picked
Scala-list
Scala
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.