Page History
...
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
//class Foo[+A] // A covariant class //class Bar[-A] // A contravariant class //class Baz[A] // An invariant class println("# Covariance") abstract class Animal { def name: String } case class Cat(name: String) extends Animal case class Dog(name: String) extends Animal def printAnimalNames(animals: List[Animal]): Unit = { println("##" + animals ) animals.foreach { animal => println(animal.name) } } val cats: List[Cat] = List(Cat("Whiskers"), Cat("Tom")) val dogs: List[Dog] = List(Dog("Fido"), Dog("Rex")) printAnimalNames(cats) printAnimalNames(dogs) println("# Contravariance") abstract class Printer[-A] { def print(value: A): Unit } class AnimalPrinter extends Printer[Animal] { def print(animal: Animal): Unit = println("The animal's name is: " + animal.name) } class CatPrinter extends Printer[Cat] { def print(cat: Cat): Unit = println("The cat's name is: " + cat.name) } val myCat: Cat = Cat("Boots") def printMyCat(printer: Printer[Cat]): Unit = { printer.print(myCat) } val catPrinter: Printer[Cat] = new CatPrinter val animalPrinter: Printer[Animal] = new AnimalPrinter printMyCat(catPrinter) printMyCat(animalPrinter) println("# Invariance") abstract class SmallAnimal extends Animal case class Mouse(name: String) extends SmallAnimal var smallAni:SmallAnimal = new Mouse("miky") println(smallAni.name) //val cat: Cat = catContainer.getValue // Oops, we'd end up with a Dog assigned to a Cat |
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
abstract class Animal {
def name: String
}
abstract class Pet extends Animal {}
class Cat extends Pet {
override def name: String = "Cat"
}
class Dog extends Pet {
override def name: String = "Dog"
}
class Lion extends Animal {
override def name: String = "Lion"
}
class PetContainer[P <: Pet](p: P) {
def pet: P = p
}
val dogContainer = new PetContainer[Dog](new Dog)
val catContainer = new PetContainer[Cat](new Cat)
// this would not compile
val lionContainer = new PetContainer[Lion](new Lion) |
Code Block | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
/*
trait Node[+B] {
def prepend(elem: B): Node[B]
}
case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend(elem: B): ListNode[B] = ListNode(elem, this)
def head: B = h
def tail: Node[B] = t
}
case class Nil[+B]() extends Node[B] {
def prepend(elem: B): ListNode[B] = ListNode(elem, this)
}*/
trait Node[+B] {
def prepend[U >: B](elem: U): Node[U]
}
case class ListNode[+B](h: B, t: Node[B]) extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
def head: B = h
def tail: Node[B] = t
}
case class Nil[+B]() extends Node[B] {
def prepend[U >: B](elem: U): ListNode[U] = ListNode(elem, this)
}
trait Bird
case class AfricanSwallow() extends Bird
case class EuropeanSwallow() extends Bird
val africanSwallowList= ListNode[AfricanSwallow](AfricanSwallow(), Nil())
val birdList: Node[Bird] = africanSwallowList
birdList.prepend(new EuropeanSwallow) |
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
...