[英]Trying to understand ClassTag and TypeTag in Scala
I am trying to understand how we can overcome type erasure in scala using ClassTag
and TypeTag
. 我试图了解如何使用ClassTag
和TypeTag
克服scala中的类型擦除。 I wrote the following examples which are generic functions that try to filter out List[TNode]
where TNode
is equal to TMatch
. 我编写了以下示例,这些示例是尝试过滤掉其中TNode
等于TMatch
List[TNode]
通用函数。 However, I expect in recognizeUsingTypeTag
, the function shall not call extractUsingClassTag
is the generic type of list is equal to TMatch
(or the message gets printed), but my assumption is apparently wrong. 不过,我希望在recognizeUsingTypeTag
,函数不得调用extractUsingClassTag
是一般类型的列表等于TMatch
(或者被打印的消息),但我的假设是错误的明显。 Thank you. 谢谢。
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")
Console: 安慰:
extractFail
List(Hello, World!)
List(Hello, World!, 123, false)
extractUsingClassTag
List(Hello, World!)
List(Hello, World!)
recognizeUsingTypeTag
List(Hello, World!)
List(Hello, World!)
Why this does not get printed for List[String] 为什么不打印List [String]
Because you specified explicit type parameters: [Any, String]
, so case _ if typeOf[TNode] =:= typeOf[TMatch]
compares typeOf[Any] =:= typeOf[String]
. 因为你指定了显式类型参数: [Any, String]
,所以case _ if typeOf[TNode] =:= typeOf[TMatch]
比较typeOf[Any] =:= typeOf[String]
。
Since you do need to specify String
for TMatch
, but want TNode
to be inferred, the usual way to do it is splitting type parameters into two lists by creating an intermediate class: 由于您确实需要为TMatch
指定String
,但希望推断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]
When you have implicit parameters like that and don't need their names , it's preferred to use context bounds : T : TypeTag : ClassTag
adds two implicit parameters of types TypeTag[T]
and ClassTag[T]
. 当你有这样的隐式参数并且不需要它们的名字时 ,最好使用上下文边界 : T : TypeTag : ClassTag
添加两个类型为TypeTag[T]
和ClassTag[T]
隐式参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.