An alternate is to allow the body to be left off entirely: record R(int x, int y) { @MyAnnotation public boolean equals(Object o); }
> On Mar 9, 2019, at 1:57 PM, Brian Goetz <brian.go...@oracle.com> wrote: > > This raises a related question, which is: what if the author likes the > default implementation, but wants to add more annotations (or Javadoc)? > > Currently, the story is decent for constructors; declaring an empty `Foo { }` > constructor recreates the default behavior. There is no equivalent for > accessors, equals, hashCode, or toString. We toyed with a “default.m()” > syntax in the past: > > record R(int x, int y) { > @MyAnnotation > public boolean equals(Object o) -> default.equals(o); > } > > which doesn’t seem so bad, and is surely better than trying (and maybe > failing) to reproduce the default behavior imperatively. > > >> On Mar 9, 2019, at 12:47 PM, Brian Goetz <brian.go...@oracle.com >> <mailto:brian.go...@oracle.com>> wrote: >> >> This came up before, but we didn’t reach a conclusion. >> >> A record component is more than just the lower-level members (fields, >> accessors, ctor params) it gets desugared too. So it seems reasonable that >> it be considered an annotatable program element, and that reflection expose >> directly the annotations on record components (separately from any >> annotations on the class members that may or may not derive from desugaring >> of records.) >> >> But, that still leaves the question of whether the desugaring should, or >> should not be, transparent to annotations. My sense is that pushing >> annotations down to fields, ctor params, and accessors _seems_ friendly, but >> also opens a number of uncomfortable questions. >> >> - Should we treat the cases where @A has a target of RECORD_COMPONENT, >> separately from the cases where it does not, such as, only push the >> annotation down to members when the target does not include >> RECORD_COMPONENT? That is, is the desire to push down annotations based on >> “well, what if we want to apply a “legacy” annotation? If so, this causes a >> migration compatibility issue; if someone adds RC to the targets list for >> @A, then when the record is recompiled, the location of the annotations will >> changed, possibly changing the behavior of frameworks that encounter the >> record. >> >> - What if @A has a target set of { field, parameter }, but for some reason >> the user does _not_ want the annotation pushed down? Tough luck? >> Redeclare the member without the annotation? >> >> - If the user explicitly redeclares the member (ctor, accessor), what >> happens? Do we still implicitly push down annotations from record >> components to the explicit member? Will this be confusing when the source >> says “@B int x() -> x”, but reflection yields both @A and @B as annotations >> on x()? >> >> All of which causes me to back up and say: what is the motivation for >> pushing these down to implicit members, other than “general friendliness”? >> Is this a migration strategy for migrating existing code to use records, >> without having to redeclare annotations on the members? And if so, how >> useful is it really? Will users want to throw the union of >> field/accessor/ctor parameter annotations on the record components just to >> gain compatibility with their existing code? >> >> My gut sense is that the stable solution is to make record component a new >> kind of target, and encourage frameworks to learn about these, rather than >> trying to fake out frameworks by emulating legacy behavior. >> >> >>> On Mar 8, 2019, at 8:43 PM, Kevin Bourrillion <kev...@google.com >>> <mailto:kev...@google.com>> wrote: >>> >>> Re: annotations, >>> >>> Doc says, "Record components constitute a new place to put annotations; >>> we'll likely want to extend the @Target meta-annotation to reflect this." >>> >>> I'm sure we discussed this before, but I also expect to be able to put any >>> METHOD-, FIELD- or PARAMETER-targeted annotation on a record component, and >>> have that annotation appear to be present on the synthesized >>> accessor/field/constructor-parameter. Is that sensible? >>> >>> (As for records themselves, I expect they are targeted with TYPE just as >>> enums/interfaces/"plain old classes" (jeesh, is there any term that means >>> the latter?).) >>> >>> >>> >>> >>> >>> >>> >>> On Fri, Mar 1, 2019 at 12:16 PM Brian Goetz <brian.go...@oracle.com >>> <mailto:brian.go...@oracle.com>> wrote: >>> I've updated the document on data classes here: >>> >>> http://cr.openjdk.java.net/~briangoetz/amber/datum.html >>> <http://cr.openjdk.java.net/~briangoetz/amber/datum.html> >>> >>> (older versions of the document are retained in the same directory for >>> historical comparison.) >>> >>> While the previous version was mostly about tradeoffs, this version >>> takes a much more opinionated interpretation of the feature, offering >>> more examples of use cases of where it is intended to be used (and not >>> used). Many of the "under consideration" flexibilities (extension, >>> mutability, additional fields) have collapsed to their more restrictive >>> form; while some people will be disappointed because it doesn't solve >>> the worst of their boilerplate problems, our conclusion is: records are >>> a powerful feature, but they're not necessarily the delivery vehicle for >>> easing all the (often self-inflicted) pain of JavaBeans. We can >>> continue to explore relief for these situations too as separate >>> features, but trying to be all things to all classes has delayed the >>> records train long enough, and I'm convince they're separate problems >>> that want separate solutions. Time to let the records train roll. >>> >>> I've also combined the information on sealed types in this document, as >>> the two are so tightly related. >>> >>> Comments welcome. >>> >>> >>> -- >>> Kevin Bourrillion | Java Librarian | Google, Inc. | kev...@google.com >>> <mailto:kev...@google.com> >