我们以此为例:
import scala.reflect._
def get[T](list: List[Any])(implicit tag: ClassTag[T]) = {
list.flatMap {
case element: T => Some(element)
case _ => None
}
}
Run Code Online (Sandbox Code Playgroud)
我可以用来从列表中get()
获取类型的值T
(例如,get[String](list)
将从该列表中给出所有字符串).
现在,我明白编译器会ClassTag[String]
自动提供类型的值.我也明白这ClassTag
是一个类型类,在幕后的某处,有一段代码可以说implicitly[ClassTag[T]].getRuntimeClass()
或者其他什么.
但是如果是这样的话,为什么我们可以在没有类标签的情况下进行模式匹配(在这种情况下我们无法区分擦除类型)?我的意思是,它是如何实现的,如果我宣布一个隐含的参数(这是由编译器自动提供),我得到一个行为,但如果我不这么做,我得到一个不同的行为?
编译器会自动将您的代码粗略地转换为:
def get[T](list: List[Any])(implicit tag: ClassTag[T]) = list.flatMap {
case (element @ tag(_: T)) => Some(element)
case _ => None
}
Run Code Online (Sandbox Code Playgroud)
ClassTag
有一个unapply(x: Any)
重载,允许它模式匹配值.我已经清理了从中获取的树reify
只显示相关部分,但这将显示完整的树:
scala.reflect.runtime.universe.reify {
def get[T](list: List[Any])(implicit tag: ClassTag[T]) = {
list.flatMap {
case element: T => Some(element)
case _ => None
}
}
}
Run Code Online (Sandbox Code Playgroud)
另见scaladoc:
编译器试图通过缠绕一个把未经检查的类型测试在模式匹配到检查那些
(_: T)
类型图案ct(_: T)
,其中ct
是ClassTag[T]
实例.在调用其他提取器之前必须进行类型测试.如果in 是不可检查的,SomeExtractor(...)
则变成了,但我们有一个实例.ct(SomeExtractor(...))
T
SomeExtractor.unapply(x: T)
ClassTag[T]