You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@groovy.apache.org by Paolo Di Tommaso <pa...@gmail.com> on 2018/09/16 16:49:19 UTC
Groovy 3.0 breaking changes
Dear all,
Currently Groovy breaks the polymorphism contract for the `equals` and
`toString` methods for objects implementing List, Set, Map interfaces. For
example:
class Mylist extends ArrayList {
Mylist(Collection c) { super(c) }
@Override boolean equals(Object o) { throw new
UnsupportedOperationException () }
@Override int hashCode() { throw new UnsupportedOperationException () }
@Override String toString() { return 'CUSTOM STRING' }
}
def l = new Mylist([1,2,3])
assert l.toString() == 'CUSTOM STRING'
assert "$l" == '[1, 2, 3]'
def q = new Mylist([1,2,3])
assert l.equals(q)
assert l == q
In the above snippet the `toString` is *not* invoked when interpolated in a
GString, also the `equals` method not invoked, not even when it's
explicitly referenced.
A similar problem for the `equals` method exists when a class implements
the `Comparable` interface. For example:
class Foo implements Comparable<Foo> {
private int x
Foo(int x) { this.x=x }
@Override int compareTo(Foo o) { throw new
IllegalArgumentException('SHOULD INVOKE EQUALS!') }
@Override boolean equals(Object o) { return this.x == o.x }
}
assert new Foo(1).equals(new Foo(1)) // OK
assert new Foo(1) == new Foo(1) // throws IllegalArgumentException:
SHOULD INVOKE EQUALS!
In this case the `==` operator uses `compareTo` instead of the `equals`
method.
I know there are historical reasons behind each of them, however they
represent really nasty inconstancies and cause of a lot of problems. I hope
that Groovy 3.0 is planning to solve these problems or at least give a
mechanism to implement a proper behaviour.
Cheers,
Paolo