AKZ
AKZ

Reputation: 876

Java imitate and, or for concatenate rule

I have a Java class like below

class MyClass {

public boolean rule1() {...}

public boolean rule2() {...}

public boolean rule3() {...}

}

now for instance I want to check the rule of above class in many ways such as :

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

and Now I am wondering that how can I implement above line with like this one?

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

Upvotes: 2

Views: 101

Answers (2)

dreamcrash
dreamcrash

Reputation: 51403

The cleaner way would be to use the functional interface Predicate:

Type Parameters:

T - the type of the input to the predicate Functional Interface: This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

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;
    }
}

But the if chain of method calls would not look like you are looking for, namely:

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

Otherwise, you would have to implement the Builder pattern, and implement the and(), or(), and accept methods. For instance:

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()) {
            // ...
        }
    }
}

Naturally, the accept method would have to be much more robust, this is just to show what would the design look like.

Upvotes: 1

Andrew
Andrew

Reputation: 49606

Have a look at Predicate<T> and its and or or.

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

It might look less readable than the version you mentioned, renaming MyClass to something more meaningful would help. If it doesn't work for you, consider writing a Builder. Good complex examples of which can be found in, let's say, dynamic SQL builders (for example, jooq).

Upvotes: 1

Related Questions