scala - 试图理解 Scala 中的 ClassTag 和 TypeTag
问题描述
我试图了解我们如何在 scala 中使用ClassTag
and来克服类型擦除TypeTag
。我编写了以下示例,这些示例是通用函数,它们试图过滤掉List[TNode]
where TNode
is equal to TMatch
。但是,我希望在 中recognizeUsingTypeTag
,函数不应调用 extractUsingClassTag
是列表的通用类型等于TMatch
(或消息被打印),但我的假设显然是错误的。谢谢你。
object Extractor {
import scala.reflect.ClassTag
def extractFail[TNode, TMatch](list: List[TNode]) = list.filter {
case _: TMatch => true
case _ => false
}.map(x => x.asInstanceOf[TMatch])
def extractUsingClassTag[TNode, TMatch](list: List[TNode])(implicit tag1: ClassTag[TNode], tag2: ClassTag[TMatch]) = list.filter {
case _: TMatch => true
case _ => false
}.map(x => x.asInstanceOf[TMatch])
import scala.reflect.runtime.universe._
def recognizeUsingTypeTag[TNode, TMatch](list: List[TNode])(implicit tag1: TypeTag[TNode], tag2: TypeTag[TMatch], tag3: ClassTag[TNode], tag4: ClassTag[TMatch]) = list match {
case _ if typeOf[TNode] =:= typeOf[TMatch] => {
//
// Why this does not get printed for List[String]
//
println("This should get printed when called for homogeneous")
list.asInstanceOf[List[TMatch]]
}
case _ => extractUsingClassTag[TNode, TMatch](list)
}
}
val homogeneous: List[String] = List("Hello", "World!")
val heterogeneous: List[Any] = List("Hello", "World!", 123, false)
println("extractFail")
println(Extractor.extractFail[Any, String](homogeneous))
println(Extractor.extractFail[Any, String](heterogeneous) + "\n")
println("extractUsingClassTag")
println(Extractor.extractUsingClassTag[Any, String](homogeneous))
println(Extractor.extractUsingClassTag[Any, String](heterogeneous) + "\n")
println("recognizeUsingTypeTag")
println(Extractor.recognizeUsingTypeTag[Any, String](homogeneous))
println(Extractor.recognizeUsingTypeTag[Any, String](heterogeneous) + "\n")
安慰:
extractFail
List(Hello, World!)
List(Hello, World!, 123, false)
extractUsingClassTag
List(Hello, World!)
List(Hello, World!)
recognizeUsingTypeTag
List(Hello, World!)
List(Hello, World!)
解决方案
为什么这不会为 List[String] 打印
因为您指定了显式类型参数:[Any, String]
,所以case _ if typeOf[TNode] =:= typeOf[TMatch]
比较typeOf[Any] =:= typeOf[String]
.
由于您确实需要指定String
for TMatch
,但希望TNode
被推断,因此通常的方法是通过创建中间类将类型参数拆分为两个列表:
// in Extractor
class RecognizeUsingTypeTag[TMatch : TypeTag : ClassTag] {
def apply[TNode : TypeTag : ClassTag](list: List[TNode]) = list match {
case _ if typeOf[TNode] =:= typeOf[TMatch] => {
//
// Why this does not get printed for List[String]
//
println("This should get printed when called for homogeneous")
list.asInstanceOf[List[TMatch]]
}
case _ => extractUsingClassTag[TNode, TMatch](list)
}
}
def recognizeUsingTypeTag[TMatch : TypeTag : ClassTag] = new RecognizeUsingTypeTag[TMatch]
println(Extractor.recognizeUsingTypeTag[String].apply(homogeneous)) // inferred as apply[String]
println(Extractor.recognizeUsingTypeTag[String].apply(heterogeneous) + "\n") // inferred as apply[Any]
当您有这样的隐式参数并且不需要它们的名称时,最好使用上下文边界:T : TypeTag : ClassTag
添加两个类型的隐式参数TypeTag[T]
和ClassTag[T]
.
推荐阅读
- php - 如何将 if/else if 转换为循环
- database - 可以拆分数据库中的值和参数吗
- android - 如何从多个活动中调用单个服务?
- facebook - 批准 Facebook 上的应用程序需要多长时间?
- angular - 访问 json 中的数组对象以在 Angular 5 中显示下拉值
- visio - 向现有组添加形状会在 MS visio 中引发异常
- colors - lstlisting 代码是蓝色而不是黑色 - 关键字样式接管?
- php - 使用 PHP 从 JSON 数组中获取值
- html - 如何将 HTML 添加到文本中并将其添加到 DOM 以显示它?
- java - 无法将模型对象添加到“/”中的 jsp 视图,但相同的方法正在调用 /index