流口水中的单一继承

Single inheritance in drools

我们使用的是 drools 7.31 版本。我们有一个必须在其他规则中重复使用的大规则。我们需要的基本功能是在 SUPER 规则和 SUB 规则条件都为真时触发 SUPER 规则。似乎旧版本有 "extends" 关键字,使用它是可能的。我正在查看能够实现此目的的旧 post -

drools rules inheritance

当我尝试使用 7.31 版本时,SUPER 和 SUB 规则都独立触发。这是我要实现的目标的示例:

rule "super"
    @description("Generic super rule")
    when 
        $person : Person()
        a : PersonInput() from $person.getInput()
        if (a.getPersonId() == 1) break[pvd1]
        else if (a.getPersonId() == 2) break[pvd2]
    then System.out.println("Default then = " + a.getPersonId());
    then[pvd1] System.out.println("Super RULE has person id = " + a.getPersonId());
    then[pvd2] System.out.println("Super RULE has person id = " + a.getPersonId());
end

rule "sub" extends "super"
    @description("Sub rule")
    when
        c : PersonInput(HouseholdId == "99999") from $person.getInput()
    then
        System.out.println("Sub RULE has HouseholdId == 99999 == " + c.getPersonId());
end

我得到的输出首先是所有家庭的 personId 为 1/2 的人,然后第二条规则只打印 99999 家庭 ID。

我期望的输出只是打印 personId 1/2 of householdId 99999。

谢谢。

Drools 7.31 仍然支持 'extends' 机制。这里的问题是,当您扩展基本规则时,基本规则会触发。 (这很明显;如果基本规则无法触发,则 child 规则无法触发。如果基本 有效触发, 然后它会触发。当 child 规则触发时,它也会触发 parent 规则。)

解决此问题的传统方法是使用三个规则。 "base" 规则应该没有任何后果(即没有右手 side/then 子句)所以它只是列出了常见的条件。然后 "super" 规则的结果在扩展基本规则的规则中,没有任何额外的 'when' 条件,并且有正常的 then 子句。 "sub" 规则还扩展了 "base",包括它的附加条件,然后是它自己的结果。如果你不希望 "super" 在 "sub" 触发时触发,你可以让它们互斥。

这里有一个有意简化的例子:

rule "Base Rule"
when
  $person: Person( $input: input != null )
  PersonInput( $id: personId in (1, 2) )
then
// intentionally no 'then' clauses
end

rule "Super" extends "Base Rule"
when
  // No additional conditions, just use whatever is in Base Rule
then
  System.out.println("Person has id: " + $id);
end

rule "Sub" extends "Base Rule"
when
  PersonInput( householdId == "99999") from $input
then
  System.out.println("Household ID is 99999; id: " + $id);
end

现在如果我们不希望 "Super" 在 "Sub" 触发时触发,我们只需使其与 "Sub" 互斥:

rule "Super" extends "Base Rule"
when
  // This is the condition from Sub, inverted:
  PersonInput( householdId != "99999" ) from $input
then
  System.out.println("Person has id: " + $id);
end

基本上,当您扩展规则时,您同时扩展了 when then 子句。 parent 规则的 then 子句(后果)将在 child 规则的后果之前触发。此外,如果 child 无效,但 parent 有效,您仍然会触发 parent。因此,如果您有(比方说)3 个 child 规则和一个 parent 规则,则 parent 可能会被触发多达 4 次:一次是在它自己被评估时,然后是另外 3 次每个 child 评估一次。当您使用有状态会话和 update/insert 子句时,事情会变得特别奇怪。

我展示的 "no consequence" 基本规则模式就是从这个现实中演变而来的。按照这种模式,"Base Rule" 被解雇多少次没有区别,因为没有副作用(consequences/then 子句)。