Мне нужно пересечь типы входящих объектов с набором предопределенных.Как проверить наличие набора типов в коллекции объекта базового типа?
Необработанные подход для сканирования входящего сбора для каждого предопределенного типа:
trait Field
class Field1 extends Field
class Field2 extends Field
class Field3 extends Field
...
class FieldManager(shownFields:Iterable[Field]) {
var hiddenFields = new ArrayBuffer[Field]
var found = false
for (sf <- shownFields) {
if (sf.isInstanceOf[Field1]) {
found = true
break
}
if (!found)
hiddenFields+=new Field1
for (sf <- shownFields) {
if (sf.isInstanceOf[Field2]) {
found = true
break
}
if (!found)
hiddenFields+=new Field2
for (sf <- shownFields) {
if (sf.isInstanceOf[Field3]) {
found = true
break
}
if (!found)
hiddenFields+=new Field3
...
}
Ничего себе, это так многословным для Scala! Должен быть более короткий путь. Как шаблон функции в C++:
class FieldManager {
vector<Field*> hiddenFields, shownFields;
template<class T>
void fillHiddenType() {
FOR_EACH(Field *, field, shownFields) {
if (dynamic_cast<T*>(field))
return
hiddenFields.push_back(new T)
}
}
void fillHidden() {
fillHiddenType<Field1>();
fillHiddenType<Field2>();
fillHiddenType<Field3>();
...
}
};
В этом примере на C++ мы указываем каждый тип, который нужно отсканировать только один раз.
Ok, Scala также хорошо для его параметров типа, позволяет попробовать:
def fillHiddenType[T] {
for (sf <- shownFields)
if (sf.isInstanceOf[T])
return
hiddenFields+=new T
}
Но компилятор не нравится создавать T экземпляр: class type required but T found
. Попробуйте передать экземпляр в качестве аргумента, и появится следующая проблема. warning: abstract type T in type is unchecked since it is eliminated by erasure
и isInstanceOf[]
всегда верны! Тип T абстрагируется настолько хорошо, что полностью удаляется даже [T <: Поле] не позволяет сравнивать его с типами из нашей коллекции, показанной по умолчанию.
Вопрос: Как проверить целостность объекта данного типа в коллекции компактным способом?
Обновление На Scala 2.7.7 был протестирован следующий рабочий код. Оба ответа были полезны. Спасибо вам, ребята!
//Scala 2.7.7 misses toSet members
implicit def toSet[T](i:Iterable[T]): Set[T] = {
val rv = new HashSet[T]
rv ++= i
rv
}
def filterOut[T](all:Iterable[T], toRemove:Set[T]) = {
all.filter(x => ! toRemove.contains(x))
}
def filterOutByType[T <: AnyRef](all:Iterable[T], toFilter:Set[T]):Iterable[T] = {
def toClass(x:AnyRef) = x.getClass.asInstanceOf[Class[T]]
val allTypes = all map toClass
val extraTypes = toSet(filterOut(allTypes, toFilter map toClass))
all.filter(extraTypes contains toClass(_))
}
Я попробую это. – Basilevs
Я принимаю это, поскольку он сначала упоминает списки типов и, кажется, фактически протестирован с компилятором() – Basilevs
asInstanceOf [Класс [Поле]], часть была обязательной. – Basilevs