I\'m digging new scala reflection api and can\'t figure out why the following snippet doesn\'t work as expected. Given hierarchy (tried to simplify as much as I can):
So I think the key problem here is that you need to match against the type of msg
, but its compile-time type is Any
(from the PartialFunction
declaration). Essentially, you want a different TypeTag
for each element in your List[Any]
. But since they all have compile-time type of Any
by virtue of all being put into the same list, you're not going to get a TypeTag
that's any more specific than that.
I think what you probably want to do is use ClassTag
instead of 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))
As Ajran points out, just like the Manifest
version, you'll have to be aware of all the limitations of runtime types including erasure and boxing issues:
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)
There are some suggestions about how to make TypeTag
more useful for pattern matching (e.g. SI-6517), but I think those will only help when you're matching against an object with an useful TypeTag
, not an object with compile-time type of Any
.