Преобразование из EnumSet <A>в Set <B>, когда A наследует от B - PullRequest
5 голосов
/ 30 июня 2011

Название в значительной степени объясняет вопрос.У меня есть метод интерфейса:

Set<Field> getFieldSet()

, и у меня есть класс User, который выглядит примерно так

class User {
    enum Fields implements Field {
        USERNAME, PASSWORD;
        ...
    }
    ...
}

Теперь я хочу реализовать User getFieldSet() метод.Наивный способ кажется просто return EnumSet.allOf(Fields.class), но я получаю следующую ошибку:

> Type mismatch: cannot convert from Set<User.Fields> to Set<Field>

Кроме ручного копирования EnumSet в Set<Field>, есть ли хороший способ сделать это?

Ответы [ 4 ]

6 голосов
/ 30 июня 2011

Вы можете вернуть new HashSet<Field>(EnumSet.allOf(Fields.class));.

Это обойдёт тот факт, что вы не можете присвоить значение типа Set<User.Fields> переменной типа Set<Field>.

Кроме того, ваш интерфейс может быть Set<? extends Field> getFields() вместо.Вы можете назначить Set<User.Field> переменной захвата.

4 голосов
/ 30 июня 2011

Использование Collections.unmodifiableSet :

return Collections.<Field>unmodifiableSet(EnumSet.allOf(Fields.class));

Плюсы:

  • Нет небезопасного преобразования: операция безопасна во время выполнения
  • Возвращенный набор на самом деле Set<Field>, а не Set<? extends Field>
  • Набор не копируется, только упакован
  • Возвращенный набор не может быть видоизменен

Минусы:

  • Возвращенный набор не может быть видоизменен, но в любом случае это будет небезопасно.
1 голос
/ 30 июня 2011

Причина, по которой это не работает, заключается в том, что Set<Fields> не является подтипом Set<Field>.Например, если вы вернули Set<Fields> из вашего метода, вы можете получить ситуацию, подобную следующей:

Set<Field> fieldSet = user.getFieldSet(); //Returns an EnumSet<Fields>
fieldSet.add(new Field(){}); //Would compile, but would blow up at runtime, 
                             //because the set can only contain Fields enum 
                             //constants

Лучший вариант здесь - использовать другую реализацию набора (обычно неизменяемый набор)вернуть значения.Например:

Set<Field> getFieldSet() {
    return Collections.unmodifiableSet(EnumSet.allOf(Fields.class));
}

или, если вам нужно, чтобы набор был изменяем (обычно это не очень хорошая идея)

Set<Field> getFieldSet() {
    return new HashSet(EnumSet.allOf(Fields.class));
}
0 голосов
/ 30 июня 2011

Вот, думаю, хорошее решение.Это не совсем то, что вы хотите, но достаточно близко

import java.util.EnumSet;
import java.util.Set;

public class User {
    enum Fields implements Field {
        USERNAME,
        PASSWORD;
    }

    Set< ? extends Field> getFieldSet() {
        return EnumSet.allOf(Fields.class);
    }
}
...