【问题标题】:Groovy override compareToGroovy 覆盖 compareTo
【发布时间】:2014-07-25 20:06:37
【问题描述】:

我正在使用 Groovy 类别在 DSL 下工作,我需要覆盖/重载 == 运算符。然而known issue,当类实现Comparable 时,Groovy 将为== 运算符调用compareTo() 方法。我正在寻找一些解决方法(不是 AST 转换),以使 == 完全按照我的意愿行事。

我有以下“玩具”情况:

class Base implements Comparable<Base>{
    int a, b

    Base(int a, int b) {
        this.a = a
        this.b = b
    }

    @Override
    int compareTo(Base o) {
        return a <=> o.a //compare only a
    }
}

class BaseCategory {
    static boolean equals(Base base, o) { //complete equals
        if (o == null)
            throw new NullPointerException()
        if (o.getClass() != base.getClass())
            return false
        return base.a == o.a && base.b == o.b
    }

    static int compareTo(Base base, o) { //compatible with equals
        int c = base.a <=> o.a;
        if (c != 0)
            return c
        return base.b <=> o.b;
    }
}

现在当我运行时

use(BaseCategory) {
    Base a = new Base(1, 2)
    Base b = new Base(1, 3)
    println a == b
    println a <=> b
}

我得到了true0,而不是false-1。有什么解决办法吗?

【问题讨论】:

  • 您的equals 方法直接调用您的hashCode 方法,这不是一个好主意,但可能不是您关心的问题。 hashCode 方法方法只是返回 2 * a 所以 b 是无关紧要的。这真的是你想要的吗?
  • 这只是为了说明。我已经编辑了示例以使其更有意义。
  • 我没有看到 use 块或 mixin,类别是如何应用到这里的?
  • @NathanHughes 我已经更正了示例
  • @MikeSamuel 这些都是小问题,与这个“玩具”示例无关。即使我更仔细地实现equals()compareTo(),结果也是一样的。

标签: groovy dsl


【解决方案1】:

一个旧的 Groovy 错误[1][2] 将在 3.0 中修复。您的用例是否允许封装和委托?

class Base implements Comparable<Base>{
    int a, b

    @Override int compareTo(Base o) {
        return a <=> o.a
    }
}

class BaseDelegate {
    @Delegate Base base

    boolean equals(o) {
        if (o == null)
            throw new NullPointerException()
        if (o.getClass() != base.getClass())
            return false
        return base.a == o.a && base.b == o.b
    }

    int compareTo(o) { 
        int c = base.a <=> o.a;
        if (c != 0)
            return c
        return base.b <=> o.b;
    }
}

还有测试:

def a = new Base(a: 1, b: 2)
def b = new Base(a: 1, b: 3)

assert (a == b) == true
assert (a <=> b) == 0


def a1 = new BaseDelegate(base: a)
def b1 = new BaseDelegate(base: b)

assert (a1 == b1) == false
assert (a1 <=> b1) == -1

【讨论】:

  • 感谢您的回复!但不幸的是,我不能这样做:我有包含多种类型对象的现有 Java 库,我需要在不更改库本身的情况下重写/重载一些运算符。
  • @StanislavPoslavsky 我明白了。匿名课程听起来如何?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
  • 1970-01-01
相关资源
最近更新 更多