以下不编译。我需要先投这个人吗?
object People {
def all = List(
new Person("Jack", 33),
new Person("John", 31) with Authority,
new Person("Jill", 21),
new Person("Mark", 43)
)
}
class Person(val name: String, val age: Int)
trait Authority {
def giveOrder {
println("do your work!")
}
}
object Runner {
def main(args:List[String]) {
val boss = People.all.find { _.isInstanceOf [Authority] }.get
boss.giveOrder // This line doesnt compile
}
}
最佳答案
您认为以某种方式应该有一种机制可以让您避免强制转换,这是正确的。这样的 Actor 阵容将是丑陋和多余的,因为它无论如何已经出现在过滤器中。 find
然而,它根本不关心它得到的谓词的形状;它只是应用它并返回 Option[A]
如果 A
是集合元素的静态类型。
您需要的是collect
功能:
val boss = People.all.collect { case boss: Authority => boss }.head
collect
创建一个新集合。如果你想避免这种情况(如果你真的只对第一个元素感兴趣,它是 Authority
),以防潜在老板列表很长,你可能想切换到 view
懒惰地评估它:val boss = People.all.view.collect { case boss: Authority => boss }.head
最后,除非您绝对确定您的列表中总是至少有一个老板,否则您应该真正测试搜索是否成功,例如像这样:
val bossOpt = People.all.view.collect { case boss: Authority => boss }.headOption
bossOpt.foreach(_.giveOrder) // happens only if a boss was found
编辑:最后,如果你使用 Scala 2.9,你绝对应该使用
collectFirst
如 Kevin Wright's answer 中所述.
关于scala - 在 Scala 中使用基于类型的过滤器时如何获得正确的返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5933660/