我有一个如下定义的特征:
sealed trait MyTrait[+A] {
def name: String
def id: Long
def someType: A
}
我现在有一些案例类可以扩展这个特性,如下所示:
object MyTrait {
case class One[+A](name: String, id: Long, someField: String, someType: A) extends MyTrait[A]
case class Two[+A](name: String, id: Long, someField: String, someType: A) extends MyTrait[A]
case class Three[+A](name: String, id: Long, someType: A) extends MyTrait[A]
}
现在,我有一个可能包含其中一个案例类的List,我必须从给定的List中收集各个案例类,并使用如下的instanceOf检查:
val myBigList = List(One[SomeType], Two[SomeType], Three[SomeType], One[SomeType])
val allOnes = myBigList.collect {
case elem if elem.isInstanceOf[One[_]] => elem.asInstanceOf[One]]
}
val allTwos = myBigList.collect {
case elem if elem.isInstanceOf[Two[_]] => elem.asInstanceOf[Two]]
}
val allThrees = myBigList.collect {
case elem if elem.isInstanceOf[Three[_]] => elem.asInstanceOf[Three]]
}
有更好的方法吗?我的意思是有办法避免使用isInstanceOf和asInstanceOf吗?
答案 0 :(得分:3)
如果您想将One[String]
和One[Int]
放入一个存储桶中,这意味着如果您不关心内部类型,那就很好。
但是你可以使用foldLeft
一次通过而不是三次通过。
def bucketize(list: List[MyTrait[_]]): (List[One[_]], List[Two[_]], List[Three[_]]) = {
list.foldLeft(((List.empty[One[_]], List.empty[Two[_]], List.empty[Three[_]]))){ (r, c) =>
val ((one, two, three)) = r
c match {
case x: One[_] => ((one ++ List(x), two, three))
case x: Two[_] => ((one, two ++ List(x), three))
case x: Three[_] => ((one, two, three ++ List(x)))
}
}
}
你得到三个列表,第一个列表是List [One],第二个是List [Two]等等......
用法:
val ((one, two, three)) = bucketize(list)