9 December 2018

Covariance & Contravariance

I’ve been learning covariance and contravariance concepts in programming recently and tried to make it easy to understand.

What is covariance? Type B is a subtype of type A, if you want C[B] to be a subtype of C[A], you should use covariance

On contrary, if type B is a subtype of type A, if you want C[A] to be a subtype of C[B], you should use contravariance

Following is Scala demo of using covariance and contravariance.

object Demo {
  def main(args: Array[String]) = {
    val petStore = new PetStore()
    petStore.storePet(new Cage[Pet](new Pet()))
    petStore.storePet(new Cage[Dog](new Dog()))
    petStore.storePet(new Cage[Cat](new Cat()))
    // not allowed
    // petStore.storePet(new Cage[Tiger](new Tiger()))

    val zoo = new Zoo()
    zoo.store(new ZooCage[Tiger](new Tiger()))
    zoo.store(new ZooCage[DangerousAnimal](new DangerousAnimal()))
    zoo.store(new ZooCage[Animal](new Animal()))

    // not allowed
    // zoo.store(new ZooCage[Pet](new Pet()))
  }
}


class PetStore {
  def storePet(cage: Cage[Pet]) = {
    println(s"${cage.toString} stored")
  }
}

class Zoo {
  def store(zooCage: ZooCage[Tiger]) = {
    println(s"${zooCage.toString} caged")
  }
}


class Animal {
  override def toString(): String = {
    "An animal"
  }
}

class DangerousAnimal extends Animal {
  override def toString(): String = {
    "A Dangerous animal"
  }
}

class Pet extends Animal {
  override def toString(): String = {
    "A pet"
  }
}

class Dog extends Pet {
  override def toString(): String = {
    "A puppy"
  }
}

class Cat extends Pet {
  override def toString(): String = {
    "A kitten"
  }
}

class Tiger extends DangerousAnimal {
  override def toString(): String = {
    "A tiger"
  }
}

// covariance
class Cage[+T](animal: T) {
  override def toString: String = {
    animal.toString
  }
}
// contravariance
class ZooCage[-T](animal: T) {
  override def toString: String = {
    animal.toString
  }
}

Java also supports such features.

List<? extends A>
List<? super B>
tags: Scala - Java