Reputation: 2428
I am working under DSL using Groovy categories and I need to override/overload ==
operator. It is however known issue, that when class implements Comparable
, Groovy will call compareTo()
method for ==
operator. I'm looking for some workaround (not AST transformation) in order to make ==
do exactly what I want.
I have the following "toy" situation:
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;
}
}
Now when I run
use(BaseCategory) {
Base a = new Base(1, 2)
Base b = new Base(1, 3)
println a == b
println a <=> b
}
I got true
and 0
, instead of false
and -1
. Is there any workaround?
Upvotes: 6
Views: 3612
Reputation: 14539
An old Groovy bug[1][2] to be fixed in 3.0. Does your use case permit encapsulation and delegation?
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;
}
}
And the tests:
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
Upvotes: 5