> For the complete documentation index, see [llms.txt](https://harmeetsingh.gitbook.io/scala-type-system/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://harmeetsingh.gitbook.io/scala-type-system/phase-i/chapter-10-variance/contra-varaince.md).

# Contra-Varaince

For most of the Scala developers, **contra-variance** is most of the trickiest concepts in the Scala type system, but as per my experience if you have a clear picture of[ co-variance](/scala-type-system/phase-i/chapter-10-variance/co-variance.md) like **how it works**, **why compiler allows the parameter position**, **why not** and most important things are our varaince **secrets** than **contra-variance** is simple and easy to understand. Before proceeding to contra-variance, if you have any doubt within co-variance please go once again for clear the picture.

In contra-variance, the inheritance hierarchy arrows are going to be flip. As you can see in our **Diagram 10.1**, where `Garage[Car]` is actually a subtype of `Garage[Lamborghini]`, but always remember those flips are only for parameterized types object like `Garage[Car]`**(Garage of Car)** not with actual type hierarchy like `Car`, `Lamborghini` and more. For creating a contra-variance type  there is a special syntax like co-variance as below:&#x20;

```scala
class Garage[-T] 
```

For creating a contra-variance type, we need to use **(-)** **minus/hyphen** symbol with type parameter similar to co-variance and all position restrictions are applied but different from co-variance. Let’s create an example of contra-variance:

```scala
class Vehicle
class Car extends Vehicle
class Lamborghini extends Car

class Truck extends Vehicle
class FireTruck extends Truck

class TrainingSchool[-T] {
	def driveTheVehicle(vehicle : T) : Vehicle = vehicle.asInstanceOf[Vehicle] 
   // Using asInstanceOf just for example perspective
}

def driveTheCar(carSchool : TrainingSchool[Car], car : Car): Vehicle =  {
	carSchool.driveTheVehicle(car)
}

val carSchool = new TrainingSchool[Car]
val vehicleSchool = new TrainingSchool[Vehicle]
val lamborginiSchool = new TrainingSchool[Lamborghini]

driveTheCar(carSchool, new Car) // compiles and run successfully
res0: Vehicle = Car@4bd5849e

driveTheCar(vehicleSchool, new Car) // Mysterious but compiles and run successfully
res1:  Vehicle = Car@4832f03b

driveTheCar(lamborginiSchool, new Car) // Mysterious but compile time error
<console>:21: error: type mismatch;
 found   : TrainingSchool[Lamborghini]
 required: TrainingSchool[Car]
       driveTheCar(lamborginiSchool, new Car)

```

As in the example, some **mysterious** things are happend from **co-varaince** experience. While we passing supertype of `TrainingSchool[Vehicle]` is `TrainingSchool[Car]` to `driveTheCar(TrainingSchool[Car], Car)` method, the code compiles and run successfully but for passing subtype `TrainingSchool[Lamborghini]` , we are getting compile time error.&#x20;

This what we discussed in **contra-variance** earlier definition, where we mentioned inheritance arrows are actually flipped, now `TrainingSchool[Vehicle]` type object is a subclass of `TrainingSchool[Car]` type object but not actually hierarchy effects like `Vehicle` is a still subclass of `Car`. This is the reason, we can pass `TrainingSchool[Vehicle]` type object to `driveTheCar(TrainingSchool[Car], Car)` method but not `TrainingSchool[Lamborghini]` type object. There are rules, which we will explore step by step.&#x20;

**Like co-variance, in contra-variance, we have important catch or you can say rule**

While creating a generic type with the contra-variance flag **(-)**, the positions of the type parameter are only valid at methods arguments location as below:&#x20;

```scala
class TrainingSchool[-T] {
	def driveTheVehicle(vehicle : T): Vehicle //Valid position
	def washTheVehicle: T // Invalid position, compile time error
}
```

### Contra-Variance FAQ

**Why it allows to using type parameter T at method argument location not return type location?**

Let's explore the answer via code as below:&#x20;

![](https://lh4.googleusercontent.com/8ci2T32rP5iBS2u7a0uhGEggi39DIFiPXN4RyIEkzALGybkS5e7aIweUgKet2lNQC2pVHl6mYFtK_N5D53wSzewioYF8bPjQ_s6zvZknu8M6LNOSLH4q-El6EZRLsqAwY5b664zQ) **Below code never compile, this is for explanation purpose only.**

```scala
class TrainingSchool[-T] {
	def washTheVehicle: T // Suppose this allows and compiles
}

// while creating TrainingSchool[Car] type object 
class TrainingSchool[Car] {
	def washTheVehicle: Car // Suppose this allows and compiles
} 

// while creating TrainingSchool[Vehicle] type object 
class TrainingSchool[Vehicle] {
	def washTheVehicle: Vehicle // Suppose this allows and compiles 
} 

def carGarage(carSchool : TrainingSchool[Car]): Car = {
	carSchool.washTheVehicle
}

val carSchool = new TrainingSchool[Car]
val vehicleSchool = new TrainingSchool[Vehicle]
val lamborginiSchool = new TrainingSchool[Lamborghini]

val car: Car = driveTheCar(carSchool) // Compile and run because it reurns Car
val car : Car = driveTheCar(vehicleSchool) 
// Problem it return object of Vehicle and according to polymophsim this is invalid 
//for catch supertype object into subtype.
```

In case of passing `vehicleSchool` type object, at runtime `washTheVehicle` method from `TrainingSchool[Vehicle]` type is called, which returns `Vehicle` type object which is technical invalid to catch supertype object to subtype according to **polymorphism**, that’s why compiler gives us an error for using type parameter at return type position in conta-varaince.

**Why it doesn’t allow us to pass subtype?**

If it allows to passing subtype than we are generating the same scenario, which we discussed in co-variance where it doesn’t allow to **declaring the type parameter at method return type position, not in method arguments position**. Let's take another example:&#x20;

![](https://lh4.googleusercontent.com/8ci2T32rP5iBS2u7a0uhGEggi39DIFiPXN4RyIEkzALGybkS5e7aIweUgKet2lNQC2pVHl6mYFtK_N5D53wSzewioYF8bPjQ_s6zvZknu8M6LNOSLH4q-El6EZRLsqAwY5b664zQ) **Below code never compile, this is for explanation purpose only.**

```scala
class TrainingSchool[-T] {
	def driveTheVehicle(vehicle : T) : Vehicle = vehicle.asInstanceOf[Vehicle] 
}

// while creating TrainingSchool[Car] type object 
class TrainingSchool[Car] {
	def driveTheVehicle(vehicle : Car) : Vehicle = vehicle.asInstanceOf[Vehicle] 
}

// while creating TrainingSchool[Vehicle] type object 
class TrainingSchool[Vehicle] {
	def driveTheVehicle(vehicle : Vehicle) : Vehicle = vehicle.asInstanceOf[Vehicle] 
}

// while creating TrainingSchool[Lamborghini] type object 
class TrainingSchool[Lamborghini] {
	def driveTheVehicle(vehicle : Lamborghini) : Vehicle = vehicle.asInstanceOf[Vehicle] 
}

def driveTheCar(carSchool : TrainingSchool[Car], car : Car): Vehicle =  {
	carSchool.driveTheVehicle(car)
}

val lamborgini : Vehicle = driveTheCar(lamborginiSchool, new Jaguar) // Suppose it compiles
```

Method call `driveTheCar(lamborginiSchool, new Jaguar)` could generate **runtime exceptions** because `TrainingSchool[Car] driveTheVehicle` method could be using `Lamborghini` driving features which are not available in `Jaguar`.

**How it works for passing the supertype object?**

Let's jump to the code:

![](https://lh4.googleusercontent.com/8ci2T32rP5iBS2u7a0uhGEggi39DIFiPXN4RyIEkzALGybkS5e7aIweUgKet2lNQC2pVHl6mYFtK_N5D53wSzewioYF8bPjQ_s6zvZknu8M6LNOSLH4q-El6EZRLsqAwY5b664zQ)**Below code never compile, this is for explanation purpose only.**

```scala
class TrainingSchool[-T] {
	def driveTheVehicle(vehicle : T) : Vehicle = vehicle.asInstanceOf[Vehicle] 
}

// while creating TrainingSchool[Car] type object 
class TrainingSchool[Car] {
	def driveTheVehicle(vehicle : Car) : Vehicle = vehicle.asInstanceOf[Vehicle] 
}

// while creating TrainingSchool[Vehicle] type object 
class TrainingSchool[Vehicle] {
	def driveTheVehicle(vehicle : Vehicle) : Vehicle = vehicle.asInstanceOf[Vehicle] 
}

def driveTheCar(carSchool : TrainingSchool[Car], car : Car): Vehicle =  {
	carSchool.driveTheVehicle(car)
}

driveTheCar(vehicleSchool, new Car) // compiles and execute fine
```

The reason `driveTheCar(vehicleSchool, new Car)` method call works, because compiler knows during runtime, `TrainingSchool[Vehicle] driveTheVehicle` method call, which is using the features of `Vehicle` and compiler knows, `Car` is a subclass of `Vehicle`, that means all of the `Vehicles` features are also available in `Car`, so, there could be no problem if someone passing supertype object. This is the reason, compiles allows to passing supertype in contra-variance.&#x20;
