【问题标题】:Groovy compareTo for CustomClass and numbers/strings用于 CustomClass 和数字/字符串的 Groovy compareTo
【发布时间】:2018-12-15 23:18:08
【问题描述】:

我正在构建 DSL 并尝试定义一个自定义类 CustomClass,您可以在

等表达式中使用它
def result = customInstance >= 100 ? 'a' : 'b'
if (customInstance == 'hello') {...}

当您的类同时定义 equals 并实现 Comparable(定义 compareTo)时,Groovy 不会调用 ==

相反,Groovy 调用 compareToWithEqualityCheck,它有一个分支逻辑。除非您的自定义 DSL 类可以从 StringNumber 分配,否则您的自定义 compareTo 将不会被上述示例调用。

您不能用String 扩展CustomClass。 我觉得我错过了什么。希望你能帮我弄清楚如何实现我上面展示的一个简单的案例。

【问题讨论】:

    标签: groovy dsl


    【解决方案1】:

    这是一个简短的回答:您可以将GString 扩展为CustomClass。然后在两种情况下都会调用它的compareTo 方法——当你检查相等时和当你实际比较时。

    编辑:考虑到以下情况,它适用于 1 和 2,但不适用于 3。

    customInstance >= 100      // case 1
    customInstance == 'hallo'  // case 2
    customInstance == 10       // case 3
    

    现在我将从 Groovy 的 ScriptBytecodeAdapterDefaultTypeTransformation 的实现中解释一下我的理解。

    对于==运算符,如果实现了Comparable(并且没有简单的标识),它会尝试使用接口方法compareTo,因此与其他比较运算符使用的逻辑相同。仅当 Comparable 未实现时,它才会尝试根据一些智能类型调整来确定相等性,并作为最后的比率回退到调用 equals 方法。这发生在DefaultTypeTransformation.compareEqual#L603-L608

    对于所有其他比较运算符,例如 >=,Groovy 委托给 compareToWithEqualityCheck 方法。现在调用此方法时将equalityCheckOnly 标志设置为false,而对于第一种情况,当调用源自== 运算符时,它设置为true。同样,如果左侧是数字、字符或字符串,则会根据左侧的类型发生一些 Groovy 智能。如果没有应用,它最终会调用 DefaultTypeTransformation.compareToWithEqualityCheck#L584-L586 中的 compareTo 方法。

    现在,只有在

    !equalityCheckOnly || left.getClass().isAssignableFrom(right.getClass())
      || (right.getClass() != Object.class && right.getClass().isAssignableFrom(left.getClass())) //GROOVY-4046
      || (left instanceof GString && right instanceof String)
    

    equalityCheckOnly 的情况有一些限制,因此当我们来自 == 运算符时。虽然我无法解释所有这些,但我认为这些是为了防止在特定情况下引发异常,例如评论中提到的问题。

    为简洁起见,我在上面省略了在ScriptBytecodeAdapter 中预先处理并立即委托给equals 的情况,如果左侧和右侧都是相同类型并且是整数、双精度或长。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      • 2017-12-26
      相关资源
      最近更新 更多