Использование нестатических методов в качестве свойств перечисления с обобщениями

Я постараюсь быть кратким. Я пытаюсь сделать что-то вроде этого:

public enum Fruit {
    APPLE("Apple", appleHelper::doAppleThing),
    ORANGE("Orange", orangeHelper::doOrangeThing);

    private String name;
    private Function<String, List<T>> fruitFunction;

    Fruit(String name, Function<String, List<T>> fruitFunction) {
      this.name = name;
      this.fruitFunction = fruitFunction;
    }

    public String getName() {
      return name;
    }

    public <T> List<T> applyFruitFunction(String someString) {
      return fruitFunction.apply(someString);
    }
}

Так что позже у меня может быть такой метод, как

private <T> List<T> doFruitThing(String someString, Fruit fruit) {
    List<T> transformedFruits = fruit.applyFruitFunction(someString);

    if (transformedFruits.isEmpty()) {
        throw new FruitException("There was no fruit of type " + fruit.getName());
    }

    return transformedFruits;
}

Я столкнулся с двумя проблемами.

  1. doAppleThing и doOrangeThing не являются статическими методами и в идеале останутся такими, и я не могу найти никакого способа создать локальный экземпляр appleHelper и orangeHelper, чтобы справочник по методам работал.
  2. Даже если бы я сделал методы статическими, перечисления не могли бы иметь параметры типа, поэтому нет возможности использовать Function<String, List<T>> fruitFunction в качестве поля.

Как это можно сделать? Или лучше подойти к этому?

Вы хотите, чтобы методы были нестатическими, но инициализировали перечисление экземпляром метода? А метод не может быть установлен извне перечисления? Именно для этого и нужны статические методы. Если, с другой стороны, вы хотите, чтобы перечисление принимало экземпляры своего вспомогательного класса и использовало методы этих экземпляров, то это именно то, для чего перечисления не предназначены.

mypetlion 17.08.2018 22:27

может быть связано: stackoverflow.com/questions/8657608/…

Ray Tayek 18.08.2018 05:18

может быть связано: stackoverflow.com/questions/22588518/…

Ray Tayek 21.08.2018 05:16
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
3
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Значения Enum могут иметь собственные реализации методов. Я бы написал это так:

public enum Fruit {
    APPLE("Apple") {
        private final AppleHelper helper = new AppleHelper();

        @Override
        public <T> List<T> applyFruitFunction(String someString) {
            return helper.doAppleThing(someString);
        }
    },

    ORANGE("Orange") {
        private final OrangeHelper helper = new OrangeHelper();

        @Override
        public <T> List<T> applyFruitFunction(String someString) {
            return helper.doOrangeThing(someString);
        }
    };

    private String name;

    Fruit(String name) {
      this.name = name;
    }

    public String getName() {
      return name;
    }

    public abstract <T> List<T> applyFruitFunction(String someString);
}

Однако, если вы дойдете до того, что вам потребуется состояние для каждого экземпляра для экземпляров перечисления, то, что у вас есть, будет все меньше и меньше перечислением и в большей степени просто абстрактным базовым классом. Возможно, было бы лучше изучить более объектно-ориентированный подход, используя, например, шаблон фабрика / маховик, а не привязываться к чистому перечислению для такого рода вещей. (Трудно сказать наверняка, потому что код в вопросе, очевидно, является просто упрощенным примером.)

Вот и решение! А также исправляет неуместный конструктор.

ernest_k 17.08.2018 22:27

Это отличный ответ! Спасибо. Однако, поскольку реализация doAppleThing и doOrangeThing довольно сложна, я хочу, чтобы они принадлежали к другому классу (AppleHelper и OrangeHelper). Сделав эти методы статическими, я могу просто вызвать, но, полагаю, все еще нет способа сделать это с помощью методов экземпляра. Ну что ж, спасибо!

EaterOfFromage 20.08.2018 15:22

@EaterOfFromage: см. Мое последнее изменение - я считаю, что это то, что вы ищете.

Daniel Pryden 21.08.2018 03:47

Другие вопросы по теме