我正在构建DSL并尝试定义一个自定义类CustomClass
,您可以在类似
def result = customInstance >= 100 ? 'a' : 'b'
if (customInstance == 'hello') {...}
当您的类同时定义==
并实现equals
(定义{{1}})时,Groovy不会调用Comparable
。
相反,Groovy调用具有分支逻辑的compareTo
。并且除非您的自定义DSL类可从compareToWithEqualityCheck
或String
分配,否则您的自定义Number
不会在上述示例中被调用。
您不能用compareTo
扩展CustomClass
。
我觉得我想念什么。希望您能帮助我弄清楚如何实现如上所示的简单案例。
答案 0 :(得分:1)
以下是一个简短的答案:您可以将GString
扩展为CustomClass
。然后在两种情况下都会调用其compareTo
方法-在检查是否相等以及实际比较时。
编辑:考虑以下情况,它将适用于1和2,但不适用于3。
customInstance >= 100 // case 1
customInstance == 'hallo' // case 2
customInstance == 10 // case 3
现在,我将解释我从Groovy的ScriptBytecodeAdapter
和DefaultTypeTransformation
的实现中所了解的内容。
对于==
运算符,如果实现了Comparable(并且没有简单的标识),它将尝试使用接口方法compareTo,因此使用与其他比较运算符相同的逻辑。仅当未实现Comparable时,它才会尝试根据一些智能类型调整来确定相等性,并且当最终比率变回调用equals方法时。这发生在DefaultTypeTransformation.compareEqual#L603-L608
对于所有其他比较运算符,例如>=
,Groovy委托了compareToWithEqualityCheck
方法。现在,在将equalityCheckOnly
标志设置为false的情况下调用此方法,而在第一种情况下,其调用源自==
运算符时将其设置为true。同样,根据左侧的类型(如果是Number,Character或String),会出现一些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
的情况整数,双精度或长整数。