## OO, Variance, Type Safety

http://godfat.org/slide/2013-11-07-variance/

## Wikipedia says...

Within the type system of a programming language, a typing rule or a type constructor is:

• covariant if it preserves the ordering, ≤, of types, which orders types from more specific to more generic;
• contravariant if it reverses this ordering;
• invariant if neither of these applies.

## Wikipedia says...

...typically subroutines or functions, written to operate on elements of the supertype can also operate on elements of the subtype.

## Variance where it comes:

• Reference Assignment
``````
val animal: Animal = new Cat
((animal: Animal) => {}) apply new Cat
``````

## Variance where it comes:

• Reference Assignment
``````
val animal: Animal = new Cat
((animal: Animal) => {}) apply new Cat
``````
• Method Overriding
``````

``````

## Invariant (mutable) Array

``````
final class Array[T] extends ...
``````

## ArrayStoreException: Integer

``````
public class Unsafe{
public static void main(String[] args){
String[] a = new String;
Object[] b = a;
b = 1; // HERE!
System.out.println(b);
}
}
``````

## Covariant (immutable) List

``````
sealed abstract class List[+A] extends ...
``````

## List[Animal] < List[Cat]

``````
val animals: List[Animal] = List(new Cat)
``````

## Covariant (immutable) List

``````
sealed abstract class List[+A] extends ...
``````

## Nonsense:

``````
val what: List[Any] = 1 :: "hey" :: List()
val cats: List[Cat] = List(new Cat)
cats.contains(1) // false
``````

## Covariant (immutable) List

``````
sealed abstract class List[+A] extends ...
``````

## Arguments can't be covariant

``````
def contains(elem: Any): Boolean
``````

## Null is a subclass of everything

``````
val cat: Cat = null
val cats: List[Cat] = List(null)
``````

## But actually not really

``````
null.isInstanceOf[Cat] // false
``````

## Variance where it comes:

• Reference Assignment
``````

``````
• Method Overriding
``````
class Cat extends Animal {
override def eat(food: Animal): Animal = food
}
``````

## Given base class and self:

``````
class Animal              {
def self: Animal = this }
``````

## self could be overridden with:

``````
class Cat extends Animal  {
override
def self:    Cat = this }
``````

## It is safe as you can see...

``````
val a1: Animal = new Cat
val a2: Animal = a1.self``````

## And this works...

``````
val c1:    Cat = new Cat
val c2:    Cat = c1.self``````

## This is not allowed in Scala and most languages:

``````
class Animal                       {
def eat(food: Animal): Unit = () }
``````
``````
class Cat extends Animal           {
override // Error: override nothing
def eat(food: Object): Unit = () }``````

## Maybe it's just useless:

``````
(new Cat).eat(new Object)
``````

## Back for Function1:

• Reference Assignment
``````
val f: Function1[Cat, Animal] =
(a: Animal) => new Cat
``````
• Method Overriding
``````

``````

## Example:

``````
val f: Function1[Cat, Animal] =
(a: Animal) => new Cat
``````

## with Haskell syntax:(but it won't type check)

``````
f :: Cat -> Animal
f = (\animal -> Cat) :: Animal -> Cat
``````

## Given:

``````
trait Function1[-T, +R] extends AnyRef
``````

## Example:

``````
trait Function2[-T1, -T2, +R] extends AnyRef
``````

## Example:

``````
trait Function1[-T1, Function1[-T2, +R]]
``````

## Example:

``````
val f: Function1[Function1[Animal, Cat], Animal] =
(g: Function1[Cat, Animal]) => new Cat
``````
``````
+  ->  -  ->  +
``````