Java имитирует и, или правило конкатенации

У меня есть класс Java, как показано ниже

class MyClass {

public boolean rule1() {...}

public boolean rule2() {...}

public boolean rule3() {...}

}

теперь, например, я хочу проверить правило выше класса во многих отношениях, таких как:

MyClass myClass = new MyClass();
if (myClass.rule1() && myClass.rule2 || myClass.rule3) {}

и теперь мне интересно, как я могу реализовать вышеприведенную строку, как эта?

if (myClass.rule1().and().rule2().or().rule3().accept()) {}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
89
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Взгляните на Predicate<T> и его and или or.

MyClass instance = new MyClass();
Predicate<MyClass> predicate = MyClass::rule1;
if (predicate.and(MyClass::rule2).or(MyClass::rule3).test(instance)) {
  // todo
}

Это может выглядеть менее читабельно, чем версия, которую вы упомянули, переименование MyClass во что-то более осмысленное поможет. Если это не работает для вас, подумайте о том, чтобы написать Builder . Хорошие комплексные примеры, которые можно найти, скажем, в сборщиках динамических SQL (например, jooq).

Вы не ошиблись, я бы сказал, что это гораздо менее читаемый способ сделать это, чем исходный код.

Andy Turner 10.12.2020 20:56
Ответ принят как подходящий

Более чистым способом было бы использование функционального интерфейса Predicate:

Параметры типа:

T - тип входа в предикат Functional Интерфейс: это функциональный интерфейс, поэтому его можно использовать как цель назначения для лямбда-выражения или ссылки на метод.

public class A {

    public Predicate rule1() {
        return //some operation that returns a boolean;
    }

    public Predicate rule2() {
        return //some operation that returns a boolean;
    }

    public Predicate rule3() {
        return //some operation that returns a boolean;
    }
}

Но цепочка вызовов методов if выглядела бы не так, как вы ищете, а именно:

 if (myClass.rule1().and().rule2().or().rule3().accept()) {}

В противном случае вам пришлось бы реализовать шаблон Builder, а также реализовать методы and(), or() и accept. Например:

public class BooleanEvaluator {

    List<String> rules = new ArrayList<>();

    public BooleanEvaluator and() {
        rules.add("&&");
        return this;
    }

    public BooleanEvaluator or() {
        rules.add("or");
        return this;
    }

    public boolean accept() {
        int i = 0;
        boolean result = Boolean.parseBoolean(rules.get(0));
        while (i < rules.size() - 1) {
            if (rules.get(i).equals("&&")){
                result = result && Boolean.parseBoolean(rules.get(i + 1));
                i+=2;
            }
            else if (rules.get(i).equals("||")){
                result = result || Boolean.parseBoolean(rules.get(i + 1));
                i+=2;
            }
        }
        return false;
    }

    public BooleanEvaluator rule1() {
        boolean result = // apply the rule 1
        rules.add(String.valueOf(result));
        return this;
    }

    public BooleanEvaluator rule2() {
        boolean result = // apply the rule 2
        rules.add(String.valueOf(result));
        return this;
    }

    public BooleanEvaluator rule3() {
        boolean result = // apply the rule 3
        rules.add(String.valueOf(result));
        return this;
    }

    void some_method(){
        if (this.rule1().and().rule2().or().rule3().accept()) {
            // ...
        }
    }
}

Естественно, метод accept должен быть намного надежнее, это просто показать, как будет выглядеть дизайн.

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