我有一个class Foo extends Bar
和一个List
或其他基类集合:
val bars: Iterable[Bar]
我需要从集合中提取所有Foo
元素。以下是代码:
val fooes: Iterable[Foo] = bars
.filter(x => Try(x.isInstanceOf[Foo]).isSuccess))
.map(_.isInstanceOf[Foo])
有简洁的方法吗?
val fooes: Iterable[Foo] = bars.collect{case foo:Foo => foo}
.collect()
方法采用部分功能作为其参数。在这种情况下,仅为Foo
类型定义功能。其他所有内容都将被忽略。
一般可能值得记住的重写之夫妇
filter
后跟map
为collect
] >>isInstanceOf
后跟asInstanceOf
作为与typed pattern的模式匹配因此具有以下不鼓励的风格
bars .filter { _.isInstanceOf[Foo] } .map { _.asInstanceOf[Foo] }
可以重写为惯用风格
bars collect { case foo: Foo => foo }
请注意,键入样式的性质仍仅为runtime type check followed by runtime type cast,也就是说,它仅代表更好的样式服装,而没有增加类型安全性。例如
scala -print -e 'lazy val result: String = (42: Any) match { case v: String => v }'
扩展为类似内容>
<synthetic> val x1: Object = scala.Int.box(42); if (x1.$isInstanceOf[String]()) { <synthetic> val x2: String = (x1.$asInstanceOf[String]()); ... }
我们清楚地看到类型检查
isInstanceOf
,然后是类型转换为asInstanceOf
。