我想制作一个按类型
过滤元素的算法我做了类似的事
trait Valor
case class A() extends Valor
case class B() extends Valor
case class C() extends Valor
val list : List[Valor] = List(
A(), A(),
B(), B(), B(),
C()
)
def getOfType[T](list: List[_]) = {
list.filter {
case _ : T => true
case _ => false
}
}
getOfType[A](list)
但它的输出是
列表[任意] =列表(A(),A(),B(),B(),B(),C())
我知道它根本不会编译。但为什么它会编译并给出如此奇怪的结果?
答案 0 :(得分:4)
(如果您对可能的解决方案感兴趣;不适合评论)
首先,我们需要一些进口
import scala.reflect.ClassTag
然后我们可以告诉编译器在编译时为类型参数T
生成ClassTag
。
使用此ClassTag
,我们可以将所需的类与每个元素的类进行比较。
def getOfType[T](list: List[_])(implicit tag: ClassTag[T]): List[_] = {
list.filter { elem => tag.runtimeClass.equals(elem.getClass) }
}
现在,我们可以更进一步,返回T
的列表,而不是Any
的列表
def getOfType[T](list: List[_])(implicit tag: ClassTag[T]): List[T] = {
list.collect {
case elem if tag.runtimeClass.equals(elem.getClass) => elem.asInstanceOf[T]
}
}
有趣的是,神奇类型上的模式匹配在引入隐式ClassTag
证据后起作用,这让我们可以简化很多事情
def getOfType[T : ClassTag](list: List[_]): List[T] = {
list.collect {
case elem : T => elem
}
}
适用于这些简单的课程A
,B
& C
。但是,如果要过滤掉List[String]
等多态类,则需要使用TypeTag
s。您可以查看演示多态类型过滤的example gist。
我们可能会在函数中添加一个额外的显式Class[T]
参数,我们可以用它来进行比较。
答案 1 :(得分:3)
这是因为删除后会消除: T
(有警告),因为编译后通用方面会丢失,这意味着它无法在运行时检查泛型类型。所以基本上它根本就不做检查。该参数是任何事物的列表(List[_]
),并且过滤器根本不会过滤,因此它会生成任何内容的列表。