Skip to content

Instantly share code, notes, and snippets.

@asyncstream
Created September 8, 2019 21:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asyncstream/0bb708dd8a780370ffa9489ae547e01e to your computer and use it in GitHub Desktop.
Save asyncstream/0bb708dd8a780370ffa9489ae547e01e to your computer and use it in GitHub Desktop.
package com.asyncstream.scala.variance
object Invariance {
trait Traveler{
def travel(): Unit
}
trait Trip{
def start(): Unit
def stop(): Unit
}
class MountainTrip[T] extends Trip{
def start(): Unit = {}
def stop(): Unit = {}
def add(traveler: T): Unit = {}
def remove(traveler: T): Unit = {}
def participants(): Iterable[T] = {return null}
}
class MotorTraveler(name:String) extends Traveler{
def travel():Unit = {}
};
class TwoWheelerTraveler(name:String) extends MotorTraveler(name:String){
override def travel():Unit = {}
};
class Biker(name:String) extends TwoWheelerTraveler(name:String);
class HarleyBiker(name:String) extends Biker(name:String)
case class SprotsHarleyBiker(name:String) extends HarleyBiker(name:String)
case class Backpacker(name:String) extends Traveler{
def travel():Unit = {}
};
case class AcademicTraveler(name:String) extends Traveler{
def travel():Unit = {}
};
val bikerTrip = new MountainTrip[Biker]();//> bikerTrip : com.asyncstream.scala.variance.Invariance.MountainTrip[com.asy
//| ncstream.scala.variance.Invariance.Biker] = com.asyncstream.scala.variance.
//| Invariance$MountainTrip@1a86f2f1
bikerTrip.add(new Biker("Paul"));
//bikerTrip.add(Backpacker("John")); // Error occured because of type mismatch.
//Trip is of a Biker trip where you are trying to add a Backpacker which is not allowed
val allBikers:List[Biker] = List(new Biker("Sam"),new HarleyBiker("John"))
//> allBikers : List[com.asyncstream.scala.variance.Invariance.Biker] = List(c
//| om.asyncstream.scala.variance.Invariance$Biker@6fadae5d, com.asyncstream.sc
//| ala.variance.Invariance$HarleyBiker@2812cbfa)
val allTwoWheelerTravelers:List[TwoWheelerTraveler] = allBikers;
//> allTwoWheelerTravelers : List[com.asyncstream.scala.variance.Invariance.Tw
//| oWheelerTraveler] = List(com.asyncstream.scala.variance.Invariance$Biker@6f
//| adae5d, com.asyncstream.scala.variance.Invariance$HarleyBiker@2812cbfa)
abstract class MotorTrip[-T] extends Trip{
def start(): Unit = {}
def stop(): Unit = {}
def register(traveler:T): Unit // in parameter is the contravarient
}
class BikerTrip extends MotorTrip[Biker]{
def register(traveler:Biker): Unit ={}
}
class HarleyTrip extends MotorTrip[HarleyBiker]{
def register(traveler:HarleyBiker): Unit ={}
}
class SprotsHarleyTrip extends MotorTrip[SprotsHarleyBiker]{
def register(traveler:SprotsHarleyBiker): Unit ={}
}
val motorBikerTrip: MotorTrip[Biker] = new BikerTrip
val harlyBikerTrip: MotorTrip[HarleyBiker] = new HarleyTrip
val sprotsHarlyBikerTrip: MotorTrip[SprotsHarleyBiker] = new SprotsHarleyTrip
val harleyBiker = new HarleyBiker("David");
def tripRegistration(motorTrip:MotorTrip[HarleyBiker]):Unit ={
motorTrip.register(harleyBiker);
}
tripRegistration(motorBikerTrip);
tripRegistration(harlyBikerTrip);
//ERROR contravariance
//tripRegistration(sprotsHarlyBikerTrip);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment