我有以下代码:
class A[+X] {
def printY[Y >: X](y: Y) = println(y)
}
class F
class G extends F
val f = new F
val g = new G
val a = new A[F]
a.printY(g)
我预计a.printY(g)
中的编译错误g
的类型G
不是F
的超类型。但在class A
中,我指出printY
方法仅接受A
类型参数的超类型,在我的示例中为F
。
为什么它能正常工作?
答案 0 :(得分:3)
因为g
也是 F
的实例。因此,Y
被推断为F
,这是F
的超类型。即:
a.printY[F](g)
然而,这不会编译:
a.printY[G](g)
答案 1 :(得分:2)
注意:如果希望 a.printY(g)
不编译,则需要重写方法:
def printY[Y](y: Y)(implicit ev: X <:< Y) = println(y)
这样编译器会将类型参数推断为G
,然后然后检查它是否是F
的超类型,而不是寻找F
的超类型1}}这也恰好是g
的可接受类型。
答案 2 :(得分:1)
试着从另外两个角度解释它为什么会起作用。
首先,如您所知,上限是 reflexive
,对于Y&gt;:X,Y的类型X或子类型是可接受的。因此,当您定义val a = new A[F]
时,printY将如下:
def printY[Y >: F](y: Y) = println(y)
当您调用a.printY(g)时,printY的类型参数将被推断为G,这也是F的类型。
其次,对于def printY[Y >: F](y: Y) = println(y)
,当您传递Y类型的实例I时,编译器将尝试查找I和F的公共父,并将结果类型作为类型参数of printY,所以你甚至可以将String,Int的值传递给printY。
a.printY[Any]("xxx")
a.printY[Any](3)