我试图了解如何使用ClassTag和TypeTag克服scala中的类型擦除问题。我编写了以下示例,这些示例是试图筛选出List[TNode] ( TNode等于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!)发布于 2019-03-25 07:16:42
为什么没有为ListString打印这个
因为您指定了显式类型参数:[Any, String],所以case _ if typeOf[TNode] =:= typeOf[TMatch]比较typeOf[Any] =:= typeOf[String]。
由于您确实需要为String指定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]当您有这样的隐式参数并且不需要它们的名称时,最好使用context bounds:T : TypeTag : ClassTag添加两个类型为TypeTag[T]和ClassTag[T]的隐式参数。
https://stackoverflow.com/questions/55329802
复制相似问题