# 逆變性（Contravariance）

``class Fruitclass Apple extends Fruitclass Node[T]``

``val f1 = new Node[Fruit]val s1: Node[Apple] = f1     // 編譯錯誤, type mismatch``

``class Fruitclass Apple extends Fruitclass Node[-T]val f1 = new Node[Fruit]val s1: Node[Apple] = f1``

``class Fruit(val price: Int, val weight: Int)class Apple(override val price: Int,             override val weight: Int) extends Fruit(price, weight)class Banana(override val price: Int,             override val weight: Int) extends Fruit(price, weight)trait Comparator[T] {    def compare(t1: T, t2: T): Int}class Basket[T](things: T*) {    def sort(comparator: Comparator[T]) {        // 進行排序...    }}``

``val b1 = new Basket(new Apple(20, 100), new Apple(25, 150))val b2 = new Basket(new Banana(30, 200), new Banana(25, 250))``

``val comparator = new Comparator[Fruit] {                      def compare(f1: Fruit, f2: Fruit) = f1.price - f2.price                 }b1.sort(comparator)   // 編譯錯誤, type mismatchb2.sort(comparator)   // 編譯錯誤, type mismatch``

b1的比較方法為compare(comparator: Comparator[Apple])，而你要傳入Comparator[Fruit]實例，所以編譯錯誤，b2 的比較方法為compare(comparator: Comparator[Banana])，而你要傳入Comparator[Fruit]實例，所以編譯錯誤，然而事實上，無論是Apple或 Banana，確實都是一種水果，也確實都有price成員，以Fruit型態取得price來進行比較其實是合理的。

``class Fruit(val price: Int, val weight: Int)class Apple(override val price: Int,             override val weight: Int) extends Fruit(price, weight)class Banana(override val price: Int,             override val weight: Int) extends Fruit(price, weight)trait Comparator[-T] {    def compare(t1: T, t2: T): Int}class Basket[T](things: T*) {    def sort(comparator: Comparator[T]) {        // 進行排序...    }}val comparator = new Comparator[Fruit] {                      def compare(f1: Fruit, f2: Fruit) = f1.price - f2.price                 }val b1 = new Basket(new Apple(20, 100), new Apple(25, 150))val b2 = new Basket(new Banana(30, 200), new Banana(25, 250))b1.sort(comparator)b2.sort(comparator)``

``class Parentclass Child extends Parentdef test(f: Child => Parent) = {}val f1 = (c: Child) => new Parentval f2 = (p: Child) => new Childval f3 = (p: Parent) => new Parenttest(f1)test(f2)test(f3)``

一個實際的應用例子如下：
``class Fruit(val price: Int, val weight: Int) {    override def toString = "Fruit(" + price + ", " + weight + ")"}class Apple(override val price: Int,             override val weight: Int) extends Fruit(price, weight) {    override def toString = "Apple(" + price + ", " + weight + ")"}class Banana(override val price: Int,             override val weight: Int) extends Fruit(price, weight) {    override def toString = "Banana(" + price + ", " + weight + ")"}class Basket[T](things: T*) {    def show(info: T => Any) = {        for(thing <- things) {            println(info(thing))        }    }}``

``def description(f: Fruit) = f.toStringdef price(f: Fruit) = f.pricedef weight(f: Fruit) = f.weightval b1 = new Basket(new Apple(20, 100), new Apple(25, 150))val b2 = new Basket(new Banana(30, 200), new Banana(25, 250))// 顯示蘋果籃各項資訊b1.show(description)b1.show(price)b1.show(weight)// 顯示香蕉籃各項資訊b2.show(description)b2.show(price)b2.show(weight)``

b1 的型態是Basket[Apple]，而顯示用的方法為show(info: Apple => Any)，由於Function1[-T1, R] 的標註，傳入的函式參數可以逆變，而傳回值可以正變，所以你所設計的description()、price()與weight()函式可以適用b1的 show()方法，也就是說，只要傳入的是一種水果（Fruit），而傳回值可以是任何資訊（Any）的函式，都可以給show()方法使用。b2可以接 受description()、price()與weight()函式也是相同。