On Jan 10, 2020, at 2:04 AM, Tagir Valeev <amae...@gmail.com> wrote: > > 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.
That’s true about methods but not about classes. Like it or not (and as Brian says we need to avoid the temptation to fix past sins), if you define a nested class without modifiers, it is public. And the same is true of fields. So your point is partly valid (default *on a method* makes it clear something is not just package-scope) but I think you are working too hard to avoid my main point: Interfaces have the bad feature you say we want to avoid, which is that (many) declarations that look like package-scoped are silently promoted to public. Besides that, “default” doesn’t convey “public”. In all cases with members of interfaces, we have schooled ourselves to watch for the absence of the modifiers to denote “public” not “package” as in other classes. The presence of “default” helps with this, but does not dispense us from the need to be basically watchful in interface bodies. (I do want to fix this, as I’ve mentioned. But it’s a separate change request.) Given that reality, and given the fact that we are not going to “fix” that “sin” of interfaces, I think it is reasonable to propose that we *benefit* from the design of interfaces in this case, by transferring the rules to records as well. > Records are not of this kind. My point here (which I see is not gaining a lot of ground with you and Brian, but it’s a point) is that records and interfaces are of a common kind, a restricted type whose semantics is required to be (largely) public. An interface is a public product of (mainly abstract) behaviors (plus optional defaults), while a record is a public product of stateless data components. I claim it is perfectly reasonable to view them as “of the same kind” and in particular to reuse whatever rules we have for interfaces for records, rather than (option C or D) make up new rules. In fact, although Brian mentioned that proposal B seems to be fixing sins of the past (a siren song) it’s exactly the opposite case here: Proposal B embraces the sins of the past (interface access defaults to public), while the favored proposals C and D try to tinker with defaults in new ways, avoiding badly set defaults from the past. Which is fixing sins? If we avoid the siren song of making a new set of (probably wrong) defaults for records, and embrace the existing rules (imperfect as they are) then it’s a choice of A or B. And of those two choices, I think B is more natural, given the similarities of interface and records (semantically restricted mostly-public types). Another advantage of embracing the interface rules is that, if we want to tweak the rules later on (say, adding a package-private or non-public modifier, or something like that) the cost of changing the rules will lead to a larger benefit, for both interfaces and records (and any other similar constructs that may come along). If we do something bespoke for records, different from classes and interfaces, the risk is that we’ll be unable to justify later fixes to the access rules, since they will have lower benefit, applying to smaller proportions of the language. Keeping things uniform between records and interfaces (or for that matter records and classes) means that we can hope to make things more uniformly better later with features like “non-public”/ “package”/“package-private”. So, FTR, my order of preference is B, C/D, A. — John