Thanks for spelling that out Brian. I withdraw my earlier +1.
> On Nov 10, 2019, at 7:36 AM, Brian Goetz <brian.go...@oracle.com> wrote:
>
> Yes, this is about the fourth time you’ve brought this up...
>
> I understand your concerns here (as I’ve said before). We’re not going to do
> anything about it right now — and I don’t want to discuss it further until
> after 14 closes. But, I will put a few points into the record for when that
> discussion resumes.
>
> I understand that it is a little weird that the constructor is public when
> the class is not. It is a little weird, but in reality, _it makes no
> difference_. Public doesn’t really mean public, it means “public, subject to
> the public-ness of my containing class, and the exported-ness of my
> containing package.” So this is really just a personal-preference argument,
> that you find this weirdness more weird than the weirdness introduce by the
> alternate (and more complex) scheme.
>
> I also understand that you are making a “for consistency” argument with how
> default constructors work. But, there are more moving parts here, so I don’t
> find the “but default constructors work this way” argument to be compelling
> in this case.
>
> What you’re missing is the accessors. A record gains a set of mandated
> members, which must be accessible. All the talk so far has been about the
> constructor, but it would be ridiculous to use a different accessibility
> scheme for the constructor as for the other mandated members. We would have
> to have the same treatment for all the mandated members (some of which must
> be public, as they come from Object.)
>
> And here’s why this scheme is not without cost. Because the accessors and
> the constructor can be explicitly specified, now we have a more complex rule
> about what accessibilities are allowed on explicit members (i.e., it should
> be OK to upgrade from package to public, but not the other way around). And
> this is a nontrivial amount of additional spec complexity compared to
> “they’re always public.” Further, if one has a package-protected record with
> explicit members, and one changes the accessibility of the record, one has to
> change the accessibility of all mandated members. So while your scheme
> (assuming it encompasses accessors too) may feel cleaner, it is also more
> expensive for both the spec and for the users, who have to internalize a more
> complex rule. (Yes, its the same as the default constructor, but: _no one
> knows this rule_, so we can’t really lean on the “but its just like something
> else they understand.”) Which is why it is by no means the slam-dunk you
> seem to think it is, and why have been unwilling to reopen this issue.
>
> We can reconsider it after the first preview.
>
>
>
>
>
>> On Nov 9, 2019, at 2:31 PM, Remi Forax <fo...@univ-mlv.fr> wrote:
>>
>> I know we already discuss that but i still don't understand why a
>> canonical constructor has to be public.
>>
>> I understand that a canonical constructor is not a simple constructor
>> because it is also used as a kind of default de-constructor, but this
>> doesn't work well with the current rules for constructors in nested
>> classes/enums and if the class is not visible, it's constructor is not
>> visible anyway.
>>
>> As Brian said in its presentation at Devoxx, records can be used to
>> represent local nominal tuples, like
>>
>> public void foo() {
>> record Pair(String name, int value);
>> ...
>> }
>>
>> If one want to add a requireNonNull using a compact constructor, it will be
>> public void foo() {
>> record Pair(String name, int value) {
>> public Pair {
>> Objects.requireNonNull(name);
>> }
>> }
>> ...
>> }
>>
>> having to declare the constructor to be public in that case seems weird.
>>
>> Mandating that the canonical constructor (hence the compact constructor) to
>> be public:
>> - goes against the idea of encapsulation that a constructor like any members
>> should be the least visible
>> - goes against the rules of default constructors (default constructor use
>> the same visibility as their class) [1]
>> - goes against the rules of constructors in enums (use private or package
>> private depending on the kind of enums) [2]
>>
>> So we a set of rules in the JLS that follows the idea that a constructor
>> should not be public by default in nested classes [1] but the rule for a
>> canonical constructor doesn't follow the same idea [3], this should be fixed.
>>
>> In my opinion, the rule for a canonical constructor should be the same as
>> the rule for a default constructor.
>>
>> regards,
>> Rémi
>>
>>
>> [1] https://docs.oracle.com/javase/specs/jls/se13/html/jls-8.html#jls-8.8.9
>> [2] https://docs.oracle.com/javase/specs/jls/se13/html/jls-8.html#jls-8.9.2
>> [3]
>> http://cr.openjdk.java.net/~gbierman/jep359/jep359-20191031/specs/records-jls.html#jls-8.10.4
>