> On Dec 5, 2017, at 10:17 AM, Brian Goetz <brian.go...@oracle.com> wrote: > > At some level, this goes to the heart of "why should records, and not tuples, > be our 'plain data' abstraction." Adding behavior to a record, **where that > behavior is derived strictly from the state**, is easy and natural. > > You can look at the "but I have to write compareTo" issue as glass 90% full > or 10% empty; a record starts life with a sensible ctor, dtor, accessors, > equals, hashCode, and toString. So adding compareTo is pretty easy. Note > also that there's no way we can reasonably derive compareTo from the state > description, since (a) not all state fields are going to be relevant for > ordering comparison and (b) the order in which they are declared may not be > the natural comparison order. So somewhere in the program the user is going > to have to write down that "a Person is compared by (lastName, firstName)", > somehow. > > We could of course invent all sorts of shorthands, but I think the > return-on-complexity there is limited, as the natural way to say this is > pretty straightforward: > > record Person(String first, String last, String age) > implements Comparable<Person> { > > private static final Comparator<Person> cc > = > Comparators.comparing(Person::last).thenComparing(Person::first); > > public int compareTo(Person other) { > return cc.compareTo(other); > } > } > > But, let's not get distracted by Billy, we care about semantics. Where are > the pitfalls you see of this approach where it might run afoul of the > "consistency between equals and compareTo is recommended" dictum?
If the automatically generated `equals` method examines all fields but the `compareTo` method does not, then there can be cases where `compareTo` says that two objects are equal but `equals` says they are unequal. Example: Person me = new Person(“Guy”, “Steele”, 63); Person myDad = new Person(“Guy”, “Steele”, 89); me.equals(myDad) ==> false me.compareTo(myDad) ==> 0 One possible solution is simply a programming discipline or documentation suggestion that says that if you write a `compareTo` method, with or without a `Comparator`, you should at least think about whether to provide an explicit definition of `equals` as well to ensure that they are consistent. In fact, we already have such a note in the documentation for `Comparator`: The natural ordering for a class C is said to be consistent with equals if and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) for every e1 and e2 of class C. . . . It is strongly recommended (though not required) that natural orderings be consistent with equals. . . . Virtually all Java core classes that implement Comparable have natural orderings that are consistent with equals. So I think the question that Rémi raises has to do with whether the language design going forward can/should better assist programmers to address this already existing recommendation. —Guy