I have a tree of boolean operations from a boolean expression that I have to run in Java. The tree would be something like this: The problem And I would need to run it in Java iteratively so that it returns me a boolean value.

boolean b = AND(isNumberEven("4"), AND(isNumberOdd("7"), isNumberEven("6"))

问题是我需要编写接口,因为在我的公司中,我们可以创建许多类,比如和,或者,hasIn数组(它可以是其他开发人员需要的任何属性).我们通常有两种类型的 node :逻辑 node ,它有两个分支;属性判断 node ,它是树的叶子.

下面我想做的是一些我认为在Java中非常错误的事情,请帮助我正确地做好它.

我的 idea 是创建两个接口,一个用于逻辑运算符,另一个用于属性判断.属性判断器需要从输入计算它的属性,而逻辑运算符需要计算两个分支,然后用两个结果计算一些东西(比如AND或OR,我们现在不关心NOT运算符).我在考虑做这些界面

class PropertyCheckingInput {
   String s; // dummy property, this object is the thing we want to verify the property on (example, if this string is an even number)

   PropertyCheckingInput(...){...} // constructor for all params
}

interface PropertyChecking {
   boolean fire(PropertyCheckingInput i);
}

class LogicOperatorInput<
   T extends LogicOperator or PropertyChecking, // it can be one or the other
   Ti extends LogicOperatorInput or PropertyCheckingInput
> {
    T left;
    Ti leftInput;
    T right;
    Ti rightInput;

    // probabily the type of leftInput should act accordingly to the type of left, but I don't know how to enforce this in Java with generics

    LogicOperatorInput(...){...} // constructor for all params
}

interface LogicOperator{
   boolean fire(LogicOperatorInput i); 
}

在这种情况下,如果我想实现类似的东西,我可以这样做

class And implements LogicOperator {
    boolean fire(LogicOperatorInput i) {
        i.left.fire(i.leftInput) && i.right.fire(i.rightInput);
    }

    And() {}

    public static void main(String[] args) {
        // expression: isNumberEven("4") AND isNumberOdd("7") AND isNumberEven("6")
        boolean b = new And().fire(new LogicOperatorInput(
            new isNumberEven(), 
            new PropertyCheckingInput("4"), 
            new And(), 
            new LogicOperatorInput(
                new isNumberOdd(), 
                new PropertyCheckingInput("7"), 
                new isNumberEven(), 
                new PropertyCheckingInput("6"))
        ));

        System.out.println(b);
    }
}

对于每个分支,我使用它们的输入执行Left和Right的函数fire,并且只关心它们的结果.然后,如果我想创建布尔表达式,我需要连接各种 node 和输入.

当然,编译器告诉我这是错误的,因为它无法推断fire()函数的正确类型.

我习惯于用Java脚本编写,它允许这种类型的东西,因为它不会判断您正在try 做什么.在Java中有没有一种方法可以做到这一点(我try 使用一些泛型或抽象类,但不起作用),或者更好的是有一种正确的方法来解决这个问题(我们有一个写成二叉树的二进制表达式,我们想通过调用与每个 node 相关联的类来解决它)?

推荐答案

你把这件事搞得太复杂了.如果您想要一个如图所示的表达式树,可以创建一个表达式树.你不需要区分"运算符"和"输入法"S.

// this represents a tree "node"
interface BooleanExpression {
    // all nodes should implement this to represent how they are evaluated
    boolean evaluate();
}

// a node can be any of these types
record IsNumberEven(int number) implements BooleanExpression {
    @Override
    public boolean evaluate() {
        return number() % 2 == 0;
    }
}

record IsNumberOdd(int number) implements BooleanExpression {
    @Override
    public boolean evaluate() {
        return number() % 2 == 1;
    }
}

record And(BooleanExpression left, BooleanExpression right) implements BooleanExpression {
    @Override
    public boolean evaluate() {
        return left().evaluate() && right().evaluate();
    }
}

用途:

boolean result = new And(
        new IsNumberEven(4),
        new And(
                new IsNumberOdd(7),
                new IsNumberEven(6)
        )
).evaluate();

如果您真的想要分离出IsNumberOdd/IsNumberEven node 的"输入",您可以这样做.只需将BooleanExpression概括为Expression<T>

interface Expression<T> {
    T evaluate();
}

record Constant<T>(T value) implements Expression<T> {
    @Override
    public T evaluate() {
        return value();
    }
}

record IsNumberEven(Expression<Integer> number) implements Expression<Boolean> {
    @Override
    public Boolean evaluate() {
        return number().evaluate() % 2 == 0;
    }
}

record IsNumberOdd(Expression<Integer> number) implements Expression<Boolean> {
    @Override
    public Boolean evaluate() {
        return number().evaluate() % 2 == 1;
    }
}

record And(Expression<Boolean> left, Expression<Boolean> right) implements Expression<Boolean> {
    @Override
    public Boolean evaluate() {
        return left().evaluate() && right().evaluate();
    }
}

用途:

boolean result = new And(
        new IsNumberEven(new Constant<>(4)),
        new And(
                new IsNumberOdd(new Constant<>(7)),
                new IsNumberEven(new Constant<>(6))
        )
).evaluate();

Java相关问答推荐

在applitcation.properties中找到的字符串中输入变量

Gmail Javi API批量处理太多请求

为什么我的画布没有显示在PFA应用程序中?

替换com. sun. jndi. dns. DnsContextFactory Wildfly23 JDK 17

如何让JFileChooser(DIRECTORIES_ONLY)从FolderName中的空白开始?

Mapstruct不能正确/完全映射属性

在Spring Boot应用程序中导致";MediaTypeNotSupportdException&qot;的映像上载

生成桥方法以解决具有相同擦除的冲突方法

有没有更快的方法在N个容器中删除重复项?

为什么我的回收视图会显示重复的列表?

Java17支持哪个MapR版本?

内存和硬盘中的Zip不同,这会导致下载后的Zip损坏

Java 11 HttpCookie.parse在解析包含JSON的Cookie时引发IlLegalArgumentException

Spring Framework6.1中引入的新RestClient是否有适合于测试的变体,就像RestTemplate和TestRestTemplate一样?

当我在Java中有一个Synchronized块来递增int时,必须声明一个变量Volatile吗?

使用MediaPlayer类在一段时间后停止播放音乐

JPA无手术同品种器械可能吗?

无法在IntStream上应用Collectors.groupingBy

基于距离的APACHE POI公式判断

如何以事务方式向ibmmq发送消息