我开始在类型参数上使用抽象类型成员 - 主要是因为它们似乎对我的类型推断更好。但是,我仍然在努力理解如何从它们定义的类型之外使用它们。例如,我无法理解为什么以下Scala程序不应该编译:
class A;
直观地说,我希望需求trait Thing
trait Describer {
type X<:Thing
def describe(x:X) = println(x)
}
object Program extends App {
def print[T <: Thing, D <: Describer]
(describer: D, thing:T)
(implicit ev: D#X =:= T)
= describer.describe(thing)
}
可以保证两种类型确实相等,因此两个实例可以互换使用,但是我得到了这个编译错误:
D#X =:= T
我误解了什么?还有另一种方法可以做我想做的事吗?或者如果失败,将error: type mismatch;
found : thing.type (with underlying type T)
required: describer.X
= describer.describe(thing)
强制转换为所需类型(thing
)是否安全?
答案 0 :(得分:5)
describer.describe
的参数类型实际上是describer.X
而不是D#X
。您必须知道的另一件事是A =:= B
也可以作为从A
到B
的转换,但(至少目前)不是相反的转换。所以以下内容应该有效。
def print[T <: Thing]
(describer: Describer, thing: T)
(implicit ev: T =:= describer.X)
= describer.describe(thing)