Non stati c ссылка на метод в конструкторе перечисления в качестве параметра - PullRequest
1 голос
/ 17 апреля 2020

Я пытаюсь сопоставить некоторые значения функциям, которые должны применяться к этим значениям. если упростить, я хочу сделать так:

import java.util.function.Supplier;

public enum SomeEnum {
    CASE1 ("val1", this::doAction1),
    CASE2 ("val2", this::doAction1),
    CASE3 ("val3", this::doAction2),
    CASE4 ("val4", this::doAction2);

    String value;
    Supplier<String> action;

    SomeEnum(String value, Supplier<String> action) {
        this.value = value;
        this.action = action;
    }

    private String doAction1() {
        return this.value + "-> action1";
    }

    private String doAction2() {
        return this.value + "-> action2";
    }
}

Он не компилируется, поскольку на SomeEnum.this нельзя ссылаться из состояния c. Я не могу сделать doAction1 & doAction2 stati c, потому что мне нужно значение из экземпляра.

Вот решение на основе if-else / switch:

import java.util.function.Supplier;

public enum SomeEnum {
    CASE1 ("val1", SomeEnum.ACTION1),
    CASE2 ("val2", SomeEnum.ACTION1),
    CASE3 ("val3", SomeEnum.ACTION2),
    CASE4 ("val4", SomeEnum.ACTION2);

    final static boolean ACTION1 = true;
    final static boolean ACTION2 = false;

    String value;
    Supplier<String> action;

    SomeEnum(String value, boolean flag) {
        this.value = value;
        this.action = flag ? this::doAction1 : this::doAction2;
    }

    private String doAction1() {
        return this.value + "-> action1";
    }

    private String doAction2() {
        return this.value + "-> action2";
    }
}

Кроме того, у меня есть более 2 методов, и мне нужно дополнительное перечисление вместо логического флага и переключателя блока в конструкторе для отображения на функции. Это перечисление было создано, чтобы избежать безумного переключателя в моем прежнем мире. Если он снова будет в конструкторе, я ничего не выиграю.

И мой главный вопрос: если в конструкторе можно использовать ссылку на метод нестати c, почему я не могу передать это как параметр? Не могли бы вы объяснить, почему это не разрешено

enum SomeEnum {
    CASE1 (this::doAction);
    Supplier<String> action;
    SomeEnum(Supplier<String> action) {
        this.action = action;
    }
private String doAction() {
            return "action";
        }
}

, когда все в порядке

enum SomeEnum {
    CASE1;
    Supplier<String> action;
    SomeEnum() {
        this.action = this::doAction;
    }
    private String doAction() {
        return "action";
    }
}

Единственное решение, которое я нашел:

import java.util.function.Supplier;

public enum SomeEnum {
    CASE1 ("val1", () -> SomeEnum.doAction1("val1")),
    CASE2 ("val2", () -> SomeEnum.doAction1("val2")),
    CASE3 ("val3", () -> SomeEnum.doAction2("val3")),
    CASE4 ("val4", () -> SomeEnum.doAction2("val4"));

    String value;
    Supplier<String> action;

    SomeEnum(String value, Supplier<String> action) {
        this.value = value;
        this.action = action;
    }

    private static String doAction1(String value) {
        return value + "-> action1";
    }

    private static String doAction2(String value) {
        return value + "-> action2";
    }
}

Может пожалуйста, оцените, если это хорошо. И почему, если это не так.

Ответы [ 2 ]

2 голосов
/ 17 апреля 2020

Вы пытаетесь реализовать то, что мне кажется в корне неверным. Знаете ли вы, что вы можете иметь абстрактные методы в перечислениях и обеспечивать их реализацию для каждой константы?

Интерфейс перечисления понятен: один метод String doAction(), который по сути является Supplier<String>, который вы использовали в качестве поля .

Вы бы все равно раздавали поле с помощью геттера, так почему бы вам просто не предоставить метод?

enum SomeEnum {
    CASE1("val1") {
        @Override
        public String doAction() {
            return this.value + "-> action1";
        }
    },
    CASE2("val2") {
        @Override
        public String doAction() {
            return this.value + "-> action2";
        }
    };

    String value;

    SomeEnum(String value) {
        this.value = value;
    }

    public abstract String doAction();
}
0 голосов
/ 17 апреля 2020

Еще один совет, мне нравится ваш вопрос.

Если у вас одинаковые логи поставщика c для всех элементов вашего enum, вы предпочтете реализовать функцию вашего поставщика только один раз. вместо абстрактного объявления.

Почему бы не попробовать ...

public enum SomeEnum {
CASE1("val1"),
CASE2("val2");

private String value;

private SomeEnum(String value) {
    this.value = value;
}

public Supplier<String> doAction() {
    return () -> {
        // Do here anything you need to do...
        return value;
    };
}

}

...