Concise method bodies with delegation and this
Victor Nazarov
asviraspossible at gmail.com
Tue Mar 12 16:26:07 UTC 2019
There was not much discussion about concise method bodies recently.
But record discussions usually touches concise methods or silently uses
concise method declarations in example code.
As I understand it concise methods almost got a consensus about basic
syntax and the only remaining corner stone are the details of delegation
and passing `this` argument to delegated method.
What I wan't to propose is to left the choice whether to pass `this` as an
argument or not to user with the help of additional syntax that is already
present in Java.
To recall basic syntax uses arrow like lambda expressions and allows to
define methods without curly braces and return keyword:
record Person(String firstName, String lastName) {
String fullName() -> firstName + lastName;
}
One of the motivating example of concise methods is an implementation of
Comparable interface with Comparator;
record Person(String firstName, String lastName)
implements Comparable<Person> {
private static final Comparator<Person> comparator =
Comparator.comparing(Person::lastName)
.thenComparing(Person::firstName);
String fullName() -> firstName + lastName;
int compareTo(Person that) -> comparator.compare(this, that);
}
Delegation form allows to declare method without the need to explicitly
write method call. `compareTo` implementation becomes:
record Person(String firstName, String lastName)
implements Comparable<Person> {
private static final Comparator<Person> comparator = // ...
String fullName() -> firstName + lastName;
int compareTo(Person that) = comparator::compare;
}
The problem with delegation form is that sometime it is desireable to pass
`this` to delegated method, but sometimes it's not:
record Person(String firstName, String lastName, List<Person> children)
implements Comparable<Person> {
private static final Comparator<Person> comparator = // ...
String fullName() -> firstName + lastName;
int compareTo(Person that) = comparator::compare;
int numberOfChildren() = children::size;
}
We want to pass `this` as a first argument into comparator::compare call,
but we don't want to pass `this` as an argument to children::size call. The
decision when to pass or not to pass `this` can be left to compiler or more
specifically to type-checker. But an implementation requires two branches
of type-inference to be performed. Furthermore both branches can
potentially succeed and there is no clear criteria what branch should be
preferred. Additionally this type-inference is inconsistent with type
inference performed for lambda expressions and method references.
What I want to propose is to left the choice whether to pass `this` as an
argument or not to user. What if there is some additional syntax to specify
when to pass this on delegation or not? But there is already such syntax.
Java 8 allows `this` to be declared as method parameter (It was done to
allow custom annotations on this type). The example from above becomes:
record Person(String firstName, String lastName, List<Person> children)
implements Comparable<Person> {
private static final Comparator<Person> comparator = // ...
String fullName() -> firstName + lastName;
// Here explicit this parameter is declared, so it's passed on to
delegated method
int compareTo(Person this, Person that) = comparator::compare;
// Here no explicit this parameter is declared, so it's not passed
int numberOfChildren() = children::size;
}
--
Victor Nazarov
More information about the amber-spec-comments
mailing list