I don't like B. The problem with B is that having a public default you may mistakenly expose an implementation detail, and it could be hard to fix this when clients start to use it. With interface methods this is less important, because if you have an implementation inside interface, you should explicitly mark it with either 'default' (meaning that it's still part of an interface) or 'private' (meaning that it's an implementation detail). But specifying an interface method with a body without a modifier at all is an error, so you will have to think. Records are not of this kind. They are not abstract, every method has an implementation, and it's perfectly valid to add a method without specifying any modifier. You will have all the tests passing, etc., but you're still doing a mistake, which is expensive to fix.
Of these options, I like C the most, though I would modify it: D. The access modifier for explicit overloads to synthetic members (canonical constructor & accessors) must be the same or more permissive than an access modifier for the record itself. The absence of access modifier means 'package-private', as usual for classes. This would require 'public' for public records, and it's nice because you will see that it's really a part of the API. On the other hand, this would reduce noise for inner/local records where you can omit the access modifier. And still, you can specify public on local records, so you can easily reduce the record visibility without the need to modify all the members. Adding an explicit package/non-public modifier is a good idea per se, but it's orthogonal to the records case. We can implement it (allowing package-private members in interfaces), yet stick with my D proposal. With best regards, Tagir Valeev. On Fri, Jan 10, 2020 at 1:52 PM John Rose <john.r.r...@oracle.com> wrote: > > P.S. The alert reader has perhaps already said, “but wait, if you > make records like interfaces, then records cannot define non-public > APIs!” Very good, alert reader, that’s just like interfaces. And we > can amend *both* by adding some way to overcome the default > “public” with a new modifier that means “I know you default to > public, and I know the normal syntax for package access is to > say nothing and obtain a different default, and I want that package > access, please.” Potential spellings for that modifier are “package” > and “non-public”. > > In interfaces, haven’t you ever wanted to define a non-public nested > class which implements the interface or carries some other interesting > implementation data? The JVM has no objection to you doing so, but > the language does. It would be helpful to allow an interface to define > a non-public nested class, for the sake of modularity. The “package” > or “non-public” modifier would support this. > > Even for garden variety classes there’s a use case for such a modifier. > Haven’t you ever wanted to mark an API point, “don’t make this public, > for heaven’s sake”? I use the comment “/*non-public*/” which drives > maintainers crazy. Saying “non-public” or “package” would be a better > way to document the intention. >