首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >试着理解Scala中的ClassTag和TypeTag

试着理解Scala中的ClassTag和TypeTag
EN

Stack Overflow用户
提问于 2019-03-25 00:10:33
回答 1查看 97关注 0票数 2

我试图了解如何使用ClassTagTypeTag克服scala中的类型擦除问题。我编写了以下示例,这些示例是试图筛选出List[TNode] ( TNode等于TMatch )的泛型函数。但是,我预计在recognizeUsingTypeTag中,函数不应该调用extractUsingClassTag是泛型列表的类型等于TMatch (或者消息被打印),但是我的假设显然是错误的。谢谢。

代码语言:javascript
复制
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")

控制台:

代码语言:javascript
复制
extractFail
List(Hello, World!)
List(Hello, World!, 123, false)

extractUsingClassTag
List(Hello, World!)
List(Hello, World!)

recognizeUsingTypeTag
List(Hello, World!)
List(Hello, World!)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-25 07:16:42

为什么没有为ListString打印这个

因为您指定了显式类型参数:[Any, String],所以case _ if typeOf[TNode] =:= typeOf[TMatch]比较typeOf[Any] =:= typeOf[String]

由于您确实需要为String指定TMatch,但希望推断TNode,所以通常的方法是通过创建一个中间类将类型参数拆分为两个列表:

代码语言:javascript
复制
// 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 boundsT : TypeTag : ClassTag添加两个类型为TypeTag[T]ClassTag[T]的隐式参数。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55329802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档