Много ли перечислений с той же функциональностью? - PullRequest
1 голос
/ 07 марта 2012

Я хотел бы создать несколько перечислений, например, описанных в этом ответе: Поиск перечисления по строковому значению

(т. Е. Перечисление с toString () и именем, котороеотличается от самого перечисления)

Можно ли как-нибудь использовать эту функциональность без необходимости переопределения ее в каждом перечислении?

Ответы [ 3 ]

3 голосов
/ 07 марта 2012

Если вы передадите список возможных значений, то вы можете сделать это без особой зависимости от типа enum.

public static <T> T findByString(T[] values, String toString) {
    Objects.requireNonNull(toString);
    for (T t : values) {
        if (toString.equals(t.toString())) {
            return t;
        }
    }
    throw new IllegalArgumentException();
}

Позвонить по номеру:

Blah blah = SomeClass.findByString(Blah.values(), str);

Вместо того, чтобы каждый раз вызывать Blah.values(), вы можете использовать его для помещения в объект, который можно передавать и использовать в общем. Возможно, другие методы добавлены позже.

public interface ByString<T> { // Choose a better name.
    T find(String toString);
}
[...]
    private static final ByString<Blah> blahs = byString(Blah.values());
[...]
    public static <T> ByString<T> byString(T[] values) {
        final T[] valuesCopy = values.clone();
        return new ByString<T>() {
            public T find(String toString) {
                return SomeClass.findByString(valuesCopy, toString);
            }
        };
    }
[...]

Позвонить по номеру:

Blah blah = blahs.find(str);

На самом деле, вы можете оптимизировать это. Сделайте toString один раз и используйте карту.

    public static <T> ByString<T> byString(T[] values) {
        final Map<String,T> byToStrings = new HashMap<>(
            (int)(values.length/0.75f)+1 // Doesn't HashMap construction suck.
        );
        for (T value : values) {
            byToStrings.put(values.toString(), value);
        }
        return new ByString<T>() {
            public T find(String toString) {
                T value = byToStrings.get(toString);
                if (value == null) {
                    throw new IllegalArgumentException();
                }
                return value;
            }
        };
    }
3 голосов
/ 07 марта 2012

Я не верю, что вы можете избежать "добавления поля и свойства" в каждом перечислении. Вы можете сделать так, чтобы ваш метод fromText делегировался обычному методу, если вы создадите интерфейс для этого свойства и передаете либо values(), либо (лучше) значение EnumSet. (Лучше: написать метод для создания без учета регистра Map и вызывать его один раз в каждом перечислении, сохраняя результат в статической переменной.)

1 голос
/ 07 марта 2012

Если у вас много перечислений с одинаковыми функциями, я бы тоже.

  • Используйте одно перечисление, так как у них много общего.
  • Используйте вспомогательный метод, который может вызывать каждое перечисление.

Java 8 сделает это проще с виртуальными расширениями. Это позволит вам определить реализацию по умолчанию для интерфейса (который должен быть вспомогательным / статическим методом)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...