假设我有Thing
的接口:
abstract class Thing[A](a_thing: A) {
def thingA = a_thing
}
我按如下方式实施Thing
:
class SpecificThing(a: String) extends Thing[String](a)
此外,假设我有一个函数,它将Thing
和一个lambda作为参数执行Thing
:
def doSomething[A](fn: Thing[A] => A, t: Thing[A]) : A = fn(t)
现在,让我们使用这些东西:
val st = new SpecificThing("hi")
val fn1: (Thing[String]) => String = (t: Thing[String]) => { t.thingA }
println(doSomething(fn1, st))
这会打印hi
。到现在为止还挺好。但是我很懒,而且我不喜欢打字,所以我将程序改为:
type MyThing = Thing[String]
val st = new SpecificThing("hi")
val fn2: (MyThing) => String = (t: MyThing) => { t.thingA }
println(doSomething(fn2, st))
这也会打印hi
。极好!编译器可以告诉SpecificThing
是Thing[String]
和MyThing
。但是这个案子呢?
val st = new SpecificThing("hi")
val fn3: (SpecificThing) => String = (t: SpecificThing) => { t.thingA }
println(doSomething(fn3, st))
现在我明白了:
Error:(14, 23) type mismatch;
found : SpecificThing => String
required: Thing[?] => ?
println(doSomething(fn3, st))
^
发生了什么?什么是Thing[?]
?
答案 0 :(得分:6)
f3
不是Thing[String] => String
,而是SpecificThing => String
。举例说明他们无法兼容的原因:
class SpecificThing2 extends Thing[String] {
def thingB = 2.0
}
val f4: SpecificThing2 => String = {
st: SpecificThing2 => f"%f${st.thingB / 3.0}"
}
val t = new Thing[String]("haha"){}
f4(t) // would be an error when f4 tried to access t.thingB
更正式地说,Function1
在其第一个类型参数Function1[-T, +R]
中是逆变。
A Thing[?]
就是它的样子;对于某种未知类型Thing[X]
,它是X
。编译器正试图推断类型A
应该是什么,但是它不能使它工作:对于某些(未知到它)类型{{1}它需要Thing[A] => A
你将A
传递给你;这是错误。