On 24 March 2025 09:20:03 GMT, "Alexandru Pătrănescu" <dreal...@gmail.com>
wrote:
>On Sun, Mar 23, 2025 at 5:20 PM Larry Garfield <la...@garfieldtech.com>
>wrote:
>
>>
>> So, how would nested classes compare to fileprivate, in terms of ability
>> to solve the problem space? As I understand it, the goal is:
>>
>> 1. Classes that can be instantiated only by the class that uses them.
>> 2. But can be returned from that class to a caller and reused as
>> appropriate.
>>
>
>
>I think the one other difference is that nested classes can access private
>variables or their outer classes.
You can achieve the same with "file private" access: in your example mark the
constructor as "file private", and put the Builder in the same file
fileprivate function __construct(private array $points) {}
If you'll excuse a brief philosophical detour, I noticed something interesting
in the Swift documentation: the description of nested classes doesn't describe
any special scope access. Instead, the description of "access levels" defines
"private" in a way that naturally includes them:
> Private access restricts the use of an entity to the enclosing declaration,
> and to extensions of that declaration that are in the same file.
It's a subtly different framing - nested types aren't breaking into the private
entity, the "private" keyword is explicitly letting nested types in.
A language could, if it chose, have different keywords for "private to exactly
this type" and "private to this type and any nested types":
strict_private function __construct(private array $points) {}
private_or_nested function __construct(private array $points) {}
Just as there are many combinations like "this class, subclasses, or other
classes in this module".
The point being that there's nothing fundamental about nested types that gives
them access to private properties. What they do is give us a new dimension to
define access levels of our choice - { contains, contained by, neither }.
File scope gives us instead the dimension { same file, different file }; and
module scope gives us { same module, different module, no module }, and maybe
some additional relationships between modules.
Rowan Tommins
[IMSoP]