rai*_*hoo 0 generics scala type-inference implicit
我在理解以下现象方面遇到了一些麻烦:
trait Trait[A] {
def traitType: String
}
object Trait {
implicit val stringTrait: Trait[String] = new Trait[String] {
def traitType: String = "string"
}
implicit val intTrait: Trait[Int] = new Trait[Int] {
def traitType: String = "int"
}
}
class Media[A] {
// works
def mediaType(implicit t: Trait[A]): String = t.traitType
// does not compile
def mediaType: String = implicitly[Trait[A]].traitType
}
object Main {
def main(args: Array[String]) {
val a = new Media[String]
val b = new Media[Int]
println(a.mediaType)
println(b.mediaType)
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,我展示了mediaType方法的两种不同实现(我在编译代码时将其中一种注释掉).但是使用隐式的版本不能编译?我收到以下错误消息:
impl.scala:19: error: could not find implicit value for parameter e: Trait[A]
def mediaType: String = implicitly[Trait[A]].traitType
^
one error found
Run Code Online (Sandbox Code Playgroud)
我明白Trait [A]没有隐含价值.我不明白为什么A不能解析为Media实例化的类型.我认为我在这里考虑的是C++模板太多了,如果有人能给我一个指向正确方向的指针,我将非常感激.
问候,raichoo
编译器需要证据,存在隐含的Trait实例A.在第一个mediaType实现中,您声明了此要求.但是在第二个实现中,从编译器的角度来看,没有这样的保证.因此,为了使其工作,您应该要求Media班级用户提供它.你可以用上下文绑定来做到这一点:
class Media[A : Trait] {
def mediaType: String = implicitly[Trait[A]].traitType
}
Run Code Online (Sandbox Code Playgroud)
这也可以更明确地编写:
class Media[A](implicit val evidence: Trait[A]) {
def mediaType: String = implicitly[Trait[A]].traitType
}
Run Code Online (Sandbox Code Playgroud)
因此换句话说,默认构造函数需要隐式evidence,用户无法在Media不提供类(显式或隐式)的情况下实例化类.