如何按类型参数化筛选Scala对象集合?

如何按类型参数化筛选Scala对象集合?,scala,reflection,types,Scala,Reflection,Types,给定一个包含变量类型项的Scala集合,我可以按类型进行筛选 trait X case class Y(y:Int) extends X case class Z(z:Int) extends X val l = List(Y(1), Y(2), Z(3), Z(4)) l.collect{case e: Y=>e} // returns List[Y] = List(Y(1), Y(2)) l.collect{case e: Z=>e} // returns List[Z] = L

给定一个包含变量类型项的Scala集合,我可以按类型进行筛选

trait X
case class Y(y:Int) extends X
case class Z(z:Int) extends X
val l = List(Y(1), Y(2), Z(3), Z(4))
l.collect{case e: Y=>e} // returns List[Y] = List(Y(1), Y(2))
l.collect{case e: Z=>e} // returns List[Z] = List(Z(3), Z(4))
我需要参数化过滤

val f = Y
l.collect{case e: f=>e} // should return List[Y] = List(Y(1), Y(2))
最后一行返回
错误:未找到:键入f
。在该
情况下
语法中不允许Scala类型的参数化


是否有类似Scala的方法来参数化此筛选操作?(可能使用的不是
collect
函数)是否需要反射?

In
val f=Y
Y
不是类型,而是伴随对象

您可以使用如下类型:

type T = Y
l.collect{case e: T=>e} // returns List[Y] = List(Y(1), Y(2))
也可以使用伴生对象,但仅限于某些参数:

val t = Y
l.collect{case e @ t(_)=>e} // returns List[Y] = List(Y(1), Y(2))

在这种情况下,您应该使用
e@t(u,u)
来表示案例类Y(y1:Int,y2:Int),
e@t(u,u,u)
来表示案例类Y(y1:Int,y2:Int,y3:Int)您不能将类型本身分配给val,但可以使用方法类型参数进行参数化:

def filterOnType[T : ClassTag](c: Traversable[Any]): Traversable[T] = {
  val tag = implicitly[ClassTag[T]];
  c.collect { case tag(t) => t } 
}
ClassTag
用于在运行时保存有关
T
的类信息。否则,
T
将被擦除,
.collect{case T:T=>T}
将与
.collect{case T:AnyRef=>T}
相同

scala> filterOnType[Y](l)
res7: Traversable[Y] = List(Y(1), Y(2))

scala> filterOnType[Z](l)
res8: Traversable[Z] = List(Z(3), Z(4))
如果您确实需要在val中保留某种类型的表示,那么在这里保留
ClassTag
就行了。
val
必须是隐式的,才能被
filterOnlyType
拾取,或者您可以直接给它:
filterOnlyType[X](l)(myClassTagForX)