【发布时间】:2015-08-03 02:55:48
【问题描述】:
我正在使用 Groovy 构建一个分析应用程序,并且无论数据格式如何,我都需要非常宽容的数学运算符。我通过运算符重载来实现这一点,在许多情况下(就我而言)改进了默认的 Groovy 类型灵活性。例如,我需要 123.45f + "05" 等于 128.45f。默认情况下,Groovy 降级为 String,我得到 123.4505。
在大多数情况下,我的重载效果很好,但不适用于比较运算符。我已经对此进行了几次讨论,但我没有得到答案,我正在寻找想法。我认识到目标是重载 compareTo()(与类似 lessThan 的东西相比),但 Groovy 似乎忽略了这一点,而是尝试自己的智能比较 - 例如DefaultTypeTransformation.compareTo(Object left, Object right),在混合类型上失败。
不幸的是,这对我来说是必须的,因为不正确地比较两个值会损害整个解决方案,而且我无法控制正在分析的某些数据类型(例如供应商数据结构)。
例如,我需要以下工作:
Float f = 123.45f;
String s = "0300";
Assert.assertTrue( f < s );
我有很多这些排列,但我尝试重载包括(假设我的 JavaTypeUtil 可以满足我的需要,如果我可以让 Groovy 调用它):
// overloads on startup, trying to catch all cases
Float.metaClass.compareTo = {
Object o -> JavaTypeUtil.compareTo(delegate, o) }
Float.metaClass.compareTo = {
String s -> JavaTypeUtil.compareTo(delegate, s) }
Object.metaClass.compareTo = {
String s -> JavaTypeUtil.compareTo(delegate, s) }
Object.metaClass.compareTo = {
Object o -> JavaTypeUtil.compareTo(delegate, o) }
当我尝试上述测试时,这些都没有被调用,而是我得到:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Float
at java.lang.Float.compareTo(Float.java:50)
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.compareToWithEqualityCheck(DefaultTypeTransformation.java:585)
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.compareTo(DefaultTypeTransformation.java:540)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareTo(ScriptBytecodeAdapter.java:690)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareLessThan(ScriptBytecodeAdapter.java:710)
at com.modelshop.datacore.generator.GroovyMathTests.testMath(GroovyMathTests.groovy:32)
通过调试,我看到
在 DefaultTypeTransformations.java:584 (2.4.3)
if (!equalityCheckOnly || left.getClass().isAssignableFrom(right.getClass())
|| (right.getClass() != Object.class && right.getClass().isAssignableFrom(left.getClass())) //GROOVY-4046
|| (left instanceof GString && right instanceof String)) {
Comparable comparable = (Comparable) left;
return comparable.compareTo(right); // <--- ***
}
在绝望的尝试中,我也尝试过重载compareLessThan,但我现在抓紧了,我不知道有什么办法可以跳到Groovy中的
Float.metaClass.compareLessThan << {
Object right -> JavaTypeUtil.compareTo(delegate, right) < 0 }
Float.metaClass.compareLessThan << {
String right -> JavaTypeUtil.compareTo(delegate, right) < 0 }
对解决方法有什么想法吗?谢谢!
【问题讨论】:
标签: groovy comparison operator-overloading