Scala 2.10 TypeTag的用法

我正在挖掘新的 scala反射api,不知道为什么以下代码段不能按预期工作.给定层次结构(尽可能简化):

import scala.reflect.runtime.universe._

trait TF[A] {
  implicit def t: TypeTag[A]

  def f[T <: A: TypeTag]: PartialFunction[Any,A] = {
    case msg: T if typeOf[T] =:= typeOf[A] => msg
  }
}

class TFilter[T: TypeTag] extends TF[T] {
  def t = typeTag[T]
}

case class Foo(x: Int)

我期望方法f过滤给定类型的对象.所以下面的代码片段应该返回Seq [Foo]

val messages = Seq(1,"hello",Foo(1))

val tFilter = new TFilter[Foo]
messages collect tFilter.f[Foo]

它实际上返回Seq [Foo],但其他消息未被过滤,这听起来像一个错误.

res1: Seq[Foo] = List(1,hello,Foo(1))

题.我使用TypeTag错误还是新的反射api的缺陷?

PS0.试用了Scala 2.10.0-RC1和2.10.0-RC2

PS1.解决方法是用Manifest替换TypeTag,所以使用以下代码收集序列将按预期返回List(Foo(1)).

trait MF[A] {
  implicit def m: Manifest[A]

  def f[T <: A: Manifest]: PartialFunction[Any,A] = {
    case msg: T if typeOf[T] =:= typeOf[A] => msg
  }
}

class MFilter[T: Manifest] extends MF[T] {
  def m = manifest[T]
}

更新:与新的Scala 2.10.0-RC2版本相同.

解决方法

所以我认为这里的关键问题是你需要匹配msg的类型,但它的编译时类型是Any(来自PartialFunction声明).实际上,您希望为List [Any]中的每个元素使用不同的TypeTag.但是由于它们都具有编译时类型为Any,因为它们都被放在同一个列表中,所以你不会得到一个比此更具体的TypeTag.

我想你可能想要做的是使用classtag而不是TypeTag:

trait TF[A] {
  implicit def t: classtag[A]

  def f: PartialFunction[Any,A] = {
    case msg: A => msg
  }
}

class TFilter[T: classtag] extends TF[T] {
  def t = classtag[T]
}

case class Foo(x: Int)

val messages = Seq(1,Foo(1),List(1),List("a"))
messages collect new TFilter[Foo].f // produces List(Foo(1))

作为Ajran points out,就像Manifest版本一样,您必须了解运行时类型的所有限制,包括擦除和拳击问题:

messages collect new TFilter[List[Int]].f // produces List(List(1),List("a"))
messages collect new TFilter[Int].f // produces List()
messages collect new TFilter[java.lang.Integer].f // produces List(1)

有一些关于如何使TypeTag对模式匹配(例如SI-6517)更有用的建议,但是我认为只有当您使用有用的TypeTag匹配对象,而不是使用编译时类型为Any的对象时,这些建议才有帮助.

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...