Generics Scala:';隐式';和类型参数
我很难理解以下现象:Generics Scala:';隐式';和类型参数,generics,scala,type-inference,implicit,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:
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)
}
}
在上面的代码片段中,我展示了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
我知道特质[A]没有隐含的价值。我不明白为什么A不能解析为媒体实例化的类型。我认为我在C++模板上考虑太多了,如果有人能给我一个指向正确的方向的指针,我将非常感激。
问候,,
raichoo如果要编译此版本:
def mediaType: String = implicitly[Trait[A]].traitType
然后需要传递Trait[A]
的隐式实例,例如,当创建Media
的新实例时。请尝试按如下方式定义媒体
:
class Media[A](implicit private val t: Trait[A]) {
def mediaType: String = t.traitType
}
使用a的一个几乎等价的定义是:
class Media[A: Trait] {
def mediaType: String = implicitly[Trait[A]].traitType
}
这就是说,如果您试图做的是保留关于参数化类型的类型参数的更多信息,那么您可能希望使用而不是您自己的机制。它们将在运行时为您提供有关A
的完整类型信息,包括A
本身是否为参数化类型:
scala> class Media[A](implicit val aManifest: Manifest[A])
defined class Media
scala> new Media[Int].aManifest
res0: Manifest[Int] = Int
scala> new Media[Seq[(Int, String)]].aManifest
res1: Manifest[Seq[(Int, String)]] = scala.collection.Seq[scala.Tuple2[Int, java.lang.String]]
编译器需要证据,证明
A
存在隐式Trait
实例。在第一个mediaType
实现中,您声明了此需求。但是在第二个实现中,从编译器的角度来看,没有这样的保证。因此,为了让它发挥作用,你应该要求媒体
类的用户提供它。您可以使用上下文绑定进行此操作:
class Media[A : Trait] {
def mediaType: String = implicitly[Trait[A]].traitType
}
这也可以写得更明确:
class Media[A](implicit val evidence: Trait[A]) {
def mediaType: String = implicitly[Trait[A]].traitType
}
因此,换句话说,默认构造函数需要隐式的
证据
,用户不提供它(显式或隐式)就无法实例化媒体
类。上面的代码只是一个示例。我知道清单,谢谢:)@raichoo是的,我只是想避免新用户阅读你的问题,感受到“灵感”,并开始从中派生自己的类似清单的变体…所以类从实例化的隐式上下文中提取Trait[A]值?(与带有隐式参数的mediaType方法相反,该方法将从调用它的上下文中提取值)