4e6*_*4e6 10 reflection scala scala-2.10
我正在挖掘新的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)
Run Code Online (Sandbox Code Playgroud)
我希望方法f
过滤给定类型的对象.所以下面的片段应该返回Seq[Foo]
val messages = Seq(1, "hello", Foo(1))
val tFilter = new TFilter[Foo]
messages collect tFilter.f[Foo]
Run Code Online (Sandbox Code Playgroud)
它实际上会返回,Seq[Foo]
但其他消息未经过滤,这听起来像一个错误.
res1: Seq[Foo] = List(1, hello, Foo(1))
Run Code Online (Sandbox Code Playgroud)
问题.我使用TypeTag
错误还是新反射api的缺陷?
PS0.试过Scala 2.10.0-RC1
和2.10.0-RC2
PS1.解决方法是替换TypeTag
为Manifest
,因此collect
序列上的以下代码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]
}
Run Code Online (Sandbox Code Playgroud)
更新:与新Scala 2.10.0-RC2
版本相同.
所以我认为这里的关键问题是你需要匹配类型msg
,但它的编译时类型是Any
(来自PartialFunction
声明).从本质上讲,你需要TypeTag
为你的每个元素添加一个不同的元素List[Any]
.但是因为它们都具有编译时类型,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, "hello", Foo(1), List(1), List("a"))
messages collect new TFilter[Foo].f // produces List(Foo(1))
Run Code Online (Sandbox Code Playgroud)
正如Ajran所指出的那样,就像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)
Run Code Online (Sandbox Code Playgroud)
关于如何使TypeTag
模式匹配更有用的一些建议(例如SI-6517),但我认为只有当你用一个有用的对象匹配时才有用TypeTag
,而不是一个编译时类型的对象Any
.
归档时间: |
|
查看次数: |
4064 次 |
最近记录: |