从超类列表中提取给定子类的元素
Extract element of given subclass from list of superclass
鉴于此代码
class Animal{}
class Dog extends Animal{}
class Cat extends Animal{}
class Pitbull extends Dog{}
object MyClass {
def main(args: Array[String]) {
val animals: List[Animal] = List(new Dog(), new Cat(), new Pitbull(), new Dog(), new Cat())
getElementOftype(animals, PitBull)
}
def getElementOftype(list: List[Animal], givenType: ???): Animal = {
}
}
我想从此列表中提取 Pitbull 类型的第一个元素,我应该如何处理?
我试过但感觉不对的方法
trait Identity{
def who: String
}
class Animal extends Identity{
override def who = "Animal"
}
class Dog extends Animal with Identity{
override def who = "Dog"
}
class Cat extends Animal with Identity{
override def who = "Cat"
}
class Pitbull extends Dog with Identity{
override def who = "Pitbull"
}
object MyClass {
def main(args: Array[String]) {
val animals: List[Animal] = List(new Dog(), new Cat(), new Pitbull(), new Dog(), new Cat())
println(getElementOftype(animals, new Pitbull()))
}
def getElementOftype(list: List[Animal], givenType: Animal): Option[Animal] = {
list.collectFirst{case s if s.who == givenType.who => s}
}
}
我只想将 Pitbull
作为参数传递,而不是实例化一个空对象。
这个方法可行,但我认为这不是最好的方法。
必须有更可扩展的方式来做到这一点。
你可以这样做(未测试,可能有一些错别字):
def getElementOftype[A <: Animal](list: List[Animal])(implicit ct: ClassTag[A]): Option[A] = {
list.collectFirst { case s: A => s }
}
需要 ClassTag
才能匹配 collectFirst
中的 A
类型。
当你写 Animal extends Identity
时,你的意思是 Animal IS an Identity,这是错误的,最好使用这种方法:
class Animal { self: Identity =>
}
这意味着无论何时你想实例化一个 Animal,你都需要给它一个 Identity,但你为什么要这样做呢?
您可以简单地使用模式匹配来过滤所需的类型,如下所示:
import scala.reflect.ClassTag
def getElementsOfType[A <: Animal : ClassTag](animals: List[Animal]): Option[A] = {
animals.filter {
case a: A => true
case _ => false
}.map(_.asInstanceOf[A]).headOption
}
headOption 是因为你的 api returns Option[A] 作为结果,你可以将它设为 return List[A] 并去掉 headOption 以防你有列表中有多个比特犬 :)
鉴于此代码
class Animal{}
class Dog extends Animal{}
class Cat extends Animal{}
class Pitbull extends Dog{}
object MyClass {
def main(args: Array[String]) {
val animals: List[Animal] = List(new Dog(), new Cat(), new Pitbull(), new Dog(), new Cat())
getElementOftype(animals, PitBull)
}
def getElementOftype(list: List[Animal], givenType: ???): Animal = {
}
}
我想从此列表中提取 Pitbull 类型的第一个元素,我应该如何处理?
我试过但感觉不对的方法
trait Identity{
def who: String
}
class Animal extends Identity{
override def who = "Animal"
}
class Dog extends Animal with Identity{
override def who = "Dog"
}
class Cat extends Animal with Identity{
override def who = "Cat"
}
class Pitbull extends Dog with Identity{
override def who = "Pitbull"
}
object MyClass {
def main(args: Array[String]) {
val animals: List[Animal] = List(new Dog(), new Cat(), new Pitbull(), new Dog(), new Cat())
println(getElementOftype(animals, new Pitbull()))
}
def getElementOftype(list: List[Animal], givenType: Animal): Option[Animal] = {
list.collectFirst{case s if s.who == givenType.who => s}
}
}
我只想将 Pitbull
作为参数传递,而不是实例化一个空对象。
这个方法可行,但我认为这不是最好的方法。 必须有更可扩展的方式来做到这一点。
你可以这样做(未测试,可能有一些错别字):
def getElementOftype[A <: Animal](list: List[Animal])(implicit ct: ClassTag[A]): Option[A] = {
list.collectFirst { case s: A => s }
}
需要 ClassTag
才能匹配 collectFirst
中的 A
类型。
当你写 Animal extends Identity
时,你的意思是 Animal IS an Identity,这是错误的,最好使用这种方法:
class Animal { self: Identity =>
}
这意味着无论何时你想实例化一个 Animal,你都需要给它一个 Identity,但你为什么要这样做呢? 您可以简单地使用模式匹配来过滤所需的类型,如下所示:
import scala.reflect.ClassTag
def getElementsOfType[A <: Animal : ClassTag](animals: List[Animal]): Option[A] = {
animals.filter {
case a: A => true
case _ => false
}.map(_.asInstanceOf[A]).headOption
}
headOption 是因为你的 api returns Option[A] 作为结果,你可以将它设为 return List[A] 并去掉 headOption 以防你有列表中有多个比特犬 :)