Генерировать перечисления во время компиляции в Java

#java #enums

#java #перечисления

Вопрос:

У меня есть перечисление Color , которое имеет около 40 цветов: BLACK , WHITE , RED и т.д.

У меня есть второе перечисление ColorListPreset , которое содержит множество коллекций Color s, таких как PRIMARY , SECONDARY , ALL , ONLY_WHITE NOT_WHITE ,,,,,,,,,,,,,,,. Мой вопрос касается этих последних двух записей.

Для каждого Color я хочу ColorListPreset содержать ONLY_ запись (коллекция размером 1) и NOT_ запись (коллекция размером n-1, например, все Color s, кроме WHITE ). Сегодня у нас используется всего пара NOT_ записей, но хотелось бы иметь по одной на Color .

В настоящее время эти коллекции обрабатываются вручную, но в идеале эти два типа должны автоматически генерироваться из Color перечисления, оставаясь доступными через ColorListPreset.NOT_WHITE таким образом, чтобы моя IDE распознала.

В качестве аргумента скажем, что доступ к этим значениям через member access (например, ColorListPreset.NOT_WHITE ) важнее, чем усилия, затрачиваемые на поддержание коллекций.

Есть ли способ добиться этого? Решение на чистой Java является идеальным. Решения, которые изменяют тип ColorListPreset , приветствуются, пока поддерживается доступ участников.

Лучшая идея, которая мне пришла в голову (хотя я еще не пытался реализовать), — это перечислить перечисления ONLY_ и NOT_ только по имени, а затем сгенерировать их коллекции в конструкторе через this.name() и Color.values() . У меня нет концепции, в которой генерируются даже имена перечислений.


Текущие примеры кода:

 public enum Color {
    BLACK("black", "0x000000"),
    GRAY("gray", "0x7f7f7f"),
    WHITE("white", "0xffffff"),
    RED("red", "0xff0000"),
    GREEN("green", "0x00ff00"),
    BLUE("blue", "0x0000ff");
    // and so on...
}
  
 public enum ColorListPreset {
    NONE(Util.arrayListOf()),
    ALL(Util.arrayListOf(Color.BLACK, Color.GRAY, Color.WHITE, Color.RED, Color.GREEN, Color.BLUE)),
    GRAYSCALE(Util.arrayListOf(Color.BLACK, Color.GRAY, Color.WHITE)),
    PRIMARY(Util.arrayListOf(Color.RED, Color.GREEN, Color.BLUE)),

    ONLY_WHITE(Util.arrayListOf(Color.WHITE)),
    NOT_WHITE(Util.arrayListOf(Color.BLACK, Color.GRAY, Color.RED, Color.GREEN, Color.BLUE));
    // and so on...
}
  

Util.arrayListOf(T... values) по сути, это просто оболочка вокруг new ArrayList<T>(Arrays.asList(values)) .

Одной из причин ColorListPreset перечисления является синтаксический сахар, например, для файлов xml. Итак, здесь играют роль внешние силы.

Комментарии:

1. Ваш вопрос был бы понятнее, если бы вы опубликовали свои перечисления.

Ответ №1:

Я бы посоветовал вам перейти ColorListPreset на какой-нибудь «конструктор» для Set<Color> или List<Color> . Это не должно быть перечислением.

 public class ColorListPreset {
    public static Set<Color> only(Color color) {
        return EnumSet.of(color);
    }

    public static Set<Color> not(Color color) {
        return EnumSet.complementOf(EnumSet.of(color));
    }

    // methods that return other color sets...
}
  

Пример использования: Для ColorListPreset.NOT_WHITE вы бы написали ColorListPreset.not(Color.WHITE) .

Комментарии:

1. Я предполагаю, что метод not вернет EnumSet.complementOf(EnumSet.of(color)) .

2. Отредактировано @MauricePerry.

3. Это звучит как гораздо лучшая идея, чем генерация (избыточного) кода.

4. Мне нравится использовать EnumSet и complementOf, но я надеялся, что не придется менять использование, поскольку существует много унаследованного кода. Хотя, это скорее «я не хочу», чем «я не могу».

5. @Phlarx Я чувствую, что для перехода к этому новому использованию можно использовать простые регулярные выражения.