Извлечь подсписок потомков в Scala - PullRequest
1 голос
/ 07 мая 2020

У меня есть 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])

Есть ли более лаконичный подход?

Ответы [ 2 ]

7 голосов
/ 07 мая 2020
val fooes: Iterable[Foo] = bars.collect{case foo:Foo => foo}

Метод .collect() принимает в качестве параметра частичную функцию. В этом случае функция определена только для типов Foo. Все остальные игнорируются.

2 голосов
/ 07 мая 2020

Пара возможных перезаписей, которые стоит запомнить

  • filter, за которым следует map как collect
  • isInstanceOf, за которым следует asInstanceOf как соответствие шаблону с набранный образец

Следовательно, следующий не рекомендуется стиль

bars
  .filter { _.isInstanceOf[Foo] }
  .map    { _.asInstanceOf[Foo] }

может быть переписан на idiomati c style

bars collect { case foo: Foo => foo }

... написание тестов типов и приведений в Scala довольно многословно. Это сделано намеренно, потому что такая практика не поощряется. Обычно лучше использовать сопоставление с типизированным образцом. Это особенно верно, если вам нужно выполнить как проверку типа, так и приведение типа, потому что обе операции затем сводятся в одно сопоставление с шаблоном.

Обратите внимание, что характер типизированного шаблона по-прежнему просто проверка типа во время выполнения с последующим приведением типа во время выполнения , то есть, это просто представляет собой более красивую стилистическую c одежду, а не повышение безопасности типов. Например,

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.

...