Тривиально найти первого члена коллекции, который имеет заданный тип:
shownFields.find(_.isInstanceOf[Field1])
, но он по-прежнему будет возвращать экземпляр Option[Field]
, а не Option[Field1]
- который вы хотитедля сильного набора текста.Здесь поможет метод сбора:
showFields.collect{case x : Field1 => x}
, который вернет Iterable[Field1]
, затем вы можете использовать headOption
, чтобы выбрать первый элемент итерируемого как Option[Field1]
, либо Some[Field1]
, еслиприсутствует или None
в противном случае:
showFields.collect{case x : Field1 => x}.headOption
Чтобы сделать его более эффективным и не вычислять ВСЕ поля1 в списке, я бы также сделал его ленивым, используя метод view
:
showFields.view.collect{case x : Field1 => x}.headOption
, а затем для предоставления значения по умолчанию, если оно не найдено, используйте метод getOrElse
, который Опции предоставляют:
showFields.view.collect{case x : Field1 => x}.headOption getOrElse (new Field1)
Обновление
Я просто перечитал вопрос, если кажется, что вы хотите, чтобы hiddenFields содержал новый экземпляр каждого подтипа Field, для которого нет элемента в showFields.
Чтобы найти все типы, представленные в Iterable
:
val shownFieldTypes = showFields.map(_.getClass).toSet
(преобразование его в набор приводит к уникальным значениям)
Если у вас есть набор интересующих вас полей:
val allFieldTypes = Set(classOf[Field1], classOf[Field2], ...)
Выможно вычесть, чтобы найти недостающие:
val hiddenFieldTypes = allFieldTypes -- shownFieldTypes
Подвох в том, что вы застряли, используяnewInstance, а рефлексия не всегда желательна ... Итак:
val protoHiddenFields = Set(new Field1, new Field2, ...)
val allFieldTypes = protoHiddenFields.map(_.getClass)
val hiddenFieldTypes = allFieldTypes -- shownFieldTypes
val hiddenFields = protohiddenFields.filter(hiddenFieldTypes contains _.getClass)
Прелесть этого подхода в том, что ваши прототипы могут быть инициализированы с использованием параметров конструктора, если вы этого хотите