groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Paolo Di Tommaso <>
Subject Groovy 3.0 breaking changes
Date Sun, 16 Sep 2018 16:49:19 GMT
Dear all,

Currently Groovy breaks the polymorphism contract for the `equals` and
`toString` methods for objects implementing List, Set, Map interfaces. For

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:

In this case the `==` operator uses `compareTo` instead of the `equals`

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.


View raw message