Final issues regarding records
Remi Forax
forax at univ-mlv.fr
Mon Apr 6 11:26:25 UTC 2020
----- Mail original -----
> De: "Gavin Bierman" <gavin.bierman at oracle.com>
> À: "amber-spec-experts" <amber-spec-experts at openjdk.java.net>
> Envoyé: Lundi 6 Avril 2020 12:10:55
> Objet: Final issues regarding records
> Dear Experts:
>
> I’d like to circle back on a couple of issues regarding records. I am finalizing
> the draft language spec - would really like to complete this very soon - so it
> would be great to get some EG feedback so we cancomplete the spec (and tweak
> the implementation as necessary). I'm especially keen to hear from anyone who
> has actually been playing with the records prototype already.
>
>
> #1. Accessibility of various record members.
>
> In an earlier email, I wrote:
>
>> Currently the mandated members are public regardless of the accessibility of
>> the record type. What should be the default accessibility for record
>> members?
>>
>> A: Currently the most popular proposal is that mandated members get
>> accessibility of the record type. Other members get package level
>> accessibility as per a regular class. (Note: it should be legal for explicit
>> declarations of mandated members to specify something _more_ accessible
>> (same rules as overriding.) )
>
> Just to clarify which members we are talking about; there are actually two
> categories to consider:
>
> 1. The implicitly declared accessor methods corresponding to the record
> components.
>
> 2. The canonical constructor (including possibly a compact constructor).
>
> For these members, the current spec and implementation require that they are
> `public` regardless of the accessibility of the enclosing record type.
>
> The question before the house is whether this is the right design. A gut
> reaction is that it feels wrong; why insist on a public accessibility regardless
> of the enclosing declaration? But after a little thought, it is not so clear
> that this is the wrong design.
>
> First, note that enums already have this implicit-members-are-`public` feature -
> the implicitly declared `values` and `valueOf` methods are `public` regardless
> of the accessibility of the enum type. As far as I am aware, this feature of
> enums has not caused any confusion (or much comment).
>
> Second, consider the case where we are using interfaces to specify the behavior
> of the record type, including the accessor methods. For example:
>
> interface I {
> int i();
> }
>
> record R(int i) implements I {}
>
> If we make R private, then there is no way we can satisfy our contract as
> interfaces can’t have private methods. In this example, there’s not a lot we can
> do other than explicitly declare the accessor method ourselves. This is a shame
> - we can't utilize the implicit declaration of accessor methods because of a
> mismatch of accessibility.
>
> Whilst this example is a little contrived, it asks whether the essence of the
> (public) contract that records satisfy, even private ones, is that they support
> accessor methods to access the values of the record components.
>
> Regarding the canonical constructor: it's indeed the case that for normal class
> declarations the *default* constructor gets the access modifier from the
> enclosing class declaration. But, this is a weak argument for *canonical*
> constructors, which are different in a number of ways already.
>
> I can see 4 options:
>
> 1. Keep the everything public option as currently spec-ed and implemented. This
> is simple to remember, and not without precedent.
>
> 2. Change the current spec and implementation so the accessor methods and
> canonical constructor inherit the accessibility from the record type. This is
> also simple to remember, but it ignores the issues with interfaces detailed
> above.
>
> 3. Incorporate both strategies: Perhaps that the canonical constructor inherits
> accessibility from the record type, whereas accessor methods are required to be
> public.
>
> 4. Some variant of (2) that can deal with the interface example (?)
>
> What are your thoughts?
1/ We have carefully to provide a path to refactor an existing class to a record,
so a record constructor and a class mandated constructor so should have the same accessibility.
In the following code, the class R should be able to be refactored to a record R.
class A {
private class R {}
private record R() {}
}
2/ I don't understand how a non public accessor can be useful,
if the class has non public access, it can use the fields instead of the accessor, so i fail to see a use case for non public accessors.
Given 1/ and 2/, the corresponding option is (3).
>
>
> #2. Annotating explicit accessor methods
>
>> Q10. Special annotation for explicit declaration of accessors.
>>
>> Tagir [6] proposes a new `@RecordAccessor` annotation to mark explicit
>> accessors, much as `@Override` is used to mark method overrides.
>>
>> A: Rather than introduce a new accessor, we will consider extending the
>> meaning of the `@Override` annotation to include this case.
>
> There's been some discussion about this, but we were hoping for more! The
> motivation for co-opting @Override is that its purpose already is to allow the
> compiler to give us better type checking because we’ve captured a bit of user
> intent, so this feels similar. However, Peter has made the excellent point that
> extending `@Override` in this way might be confusing in record declarations that
> also contain implementations of methods from interfaces.
>
> Essentially, I think our options are:
>
> 1. Do nothing. (We can come back to this at the next release.)
>
> 2. Co-op `@Override`
>
> 3. Invent a new annotation, as suggested by Tagir.
Co-op @Overrride.
>
>
> Any further thoughts ?
>
>
> ---
>
> Thanks for your consideration. I look forward to hearing your feedback.
regards,
Rémi
>
> Best wishes,
> Gavin
More information about the amber-spec-experts
mailing list