trait Function1[-T1, +R] extends AnyRef { self => /** Apply the body of this function to the argument. * @return the result of function application. */defapply(v1: T1): R...overridedeftoString() ="<function1>"}
我们知道类似 A=>B 的形式在scala中是可以自动被转换为Function1的形式。
scala>var f: Int=>Int = i=>i+1f: Int => Int = <function1>
实际上其会被转换成为如下的形式:
val f: Int => Int =new Function1[Int,Int] {defapply(i: Int): Int = i +1}
假如我们定义了三个class 如下:
class CSuper { defmsuper() = println("CSuper") } class C extends CSuper { defm() = println("C") }class CSub extends C { defmsub() = println("CSub") }
我们可以定义如下几个f:
var f: C => C = (c: C) =>new C // ➋f = (c: CSuper) =>new CSub // ➌f = (c: CSuper) =>new C // ➍f = (c: C) =>new CSub // ➎f = (c: CSub) =>new CSuper // ➏ 编译错误!
根据Function1[-T1, +R]的定义,2-5可以通过编译,而6会编译失败。
怎么理解6呢? 这里我们要区分两个概念,函数的定义类型和函数的运行类型。
这里f的定义类型是 C=>C。 当f = (c: CSub) => new CSuper时,它的实际apply方法就是:
scala>trait MyFunction2[+T1, +T2, -R] {|defapply(v1:T1, v2:T2): R =???| }<console>:37: error: contravariant typeR occurs in covariant positionin type (v1: T1, v2: T2)R of method applydefapply(v1:T1, v2:T2): R =???^<console>:37: error: covariant typeT1 occurs in contravariant positionin typeT1 of value v1defapply(v1:T1, v2:T2): R =???^<console>:37: error: covariant typeT2 occurs in contravariant positionin typeT2 of value v2defapply(v1:T1, v2:T2): R =???^