【发布时间】:2012-07-03 23:19:38
【问题描述】:
假设我可以控制这两个类并且我需要协变过滤,那么根据这些对象的类型参数过滤对象集合的最佳方法是什么?
下面是一些不能正常工作的代码:
trait Foo
case class Foo1() extends Foo
trait ReadableFoo extends Foo {def field: Int}
case class Foo2(field: Int, flag: Boolean) extends ReadableFoo
case class Foo3(field: Int, name: String) extends ReadableFoo
case class Bar[+F <: Foo](foo: F)
val seq = Seq(
Bar[Foo1](Foo1()),
Bar[Foo2](Foo2(1,true)),
Bar[Foo3](Foo3(1,"Fooz"))
)
// Should keep one
val first = seq collect {case x: Bar[Foo2] => x}
// Should keep two
val both = seq collect {case x: Bar[ReadableFoo] => x}
现在,我知道这是因为 case x: Bar[Foo1] 在编译后通过类型擦除转换为 case x: Bar[_]。我一直无法使用清单来解决这个问题。有没有办法将成员类型(即memberType = F)添加到Bar,我可以像case x if (x.memberType <:< ReadableFoo) => x一样打开?
更新
0__ 很快找到了解决原始问题的好方法。当 case 类字段本身是一个集合时,会稍作修改:
case class Bar[+F <: Foo](foo: Seq[F])
val seq = Seq(
Bar[Foo1](Seq(Foo1())),
Bar[Foo2](Seq(Foo2(1,true))),
Bar[ReadableFoo](Seq(Foo2(1,true), Foo3(1,"Fooz")))
)
// Should keep one
val first = seq collect {case x: Bar[Foo2] => x}
// Should keep two
val both = seq collect {case x: Bar[ReadableFoo] => x}
我不确定这是否可行,因为 Seq 可能为空,因此没有要测试的元素。
【问题讨论】:
-
This 可能会有所帮助。
-
@missingfaktor 是的,我想将所有类型参数打印到字符串,然后使用字符串树进行我自己的临时继承测试是一种方法。
标签: scala collections type-erasure