Following code is running perfectly :
abstract class Vehicle{
val name:String
}
case class Car(name: String) extends Vehicle
case class Bike(name: String) extends Vehicle
case class Parking[T](vehicle: T)
object Covariance extends App {
def parkMyVehicle(p : Parking[Vehicle]): Unit = println(s"Parking ${p.vehicle.name}")
parkMyVehicle(Parking(Car("Mercedes")))
parkMyVehicle(Parking(Bike("HD")))
}
This is bit strange, because, Parking
is not covariant.
However, following line is demanding covariant Parking
, else not getting compiled (which is expected).
parkMyVehicle(Parking[Car](Car("Mercedes")))
My question is, why parkMyVehicle(Parking(Car("Mercedes")))
was not demanding covariant Parking
?
Because inference can figure out from the context what type should be. I.e.
parkMyVehicle(Parking(Car("Mercedes")))
// ^ ---------------------^ What's the type of that?
since parkMyVehicle
takes Parking[Vehicle]
, that what the type should be from compiler PoV. So the expression gets typed with an upcast to a superclass:
parkMyVehicle(Parking[Vehicle](Car("Mercedes"): Vehicle))
This would be different if you extract variable, however:
val p = Parking(Car("Mercedes")) // Type is first figured out to be Parking[Car]
parkMyVehicle(p) // now the type of p does not match, so it fails to compile