[swift-evolution] final + lazy + fileprivate modifiers

Joanna Carter joanna at carterconsulting.org.uk
Tue Feb 21 03:27:01 CST 2017

> Le 21 févr. 2017 à 05:21, David Waite <david at alkaline-solutions.com> a écrit :
>> The only other option that might be useful is something like 'internal extensible' to limit visibility for extensible members to the current module.
> If a type is extensible by other modules at all, I prefer that to be spelled “public”.

Indeed, I could agree with that but…

Before 'open' was added to indicate extensibility of a publicly visible class, we used to have 'public' to indicate that the class was visible anywhere and 'final' to restrict inheritance/overriding.

With classes, 'final' was good enough to indicate that a type and/or its members should not be extensible.

But in the Swift world, we now have the ability to extend almost any type, except Any and AnyObject, which appear to be protected by some deep and dark mechanism within the compiler.  So, just as those two protocols cannot be extended, should we not be looking at some generally available mechanism to prevent extensibility of any type?

And, I am not talking visibility here, just extensibility ; somehow those two concerns are often conflated and, I believe, this is the cause of much of the "lively" discussion on visibility specifiers.

> In C++ terms, it would be when I want some other class to have friend access to a function/data, but for it not to be arbitrarily accessible by subtypes

Indeed. I do wonder if some folks approach visibility control as an exercise in "what can I see" whereas, demonstrated by C++ friends, it becomes obvious that it is more about "what do I want to allow to be seen"

Is there not a value in forking this discussion into which keywords are truly about visibility control and which are about extensibility control?

> I believe the critical piece of designing access levels is for the levels to document the intent of the developer specifying the access level. Does “extensible” indicate that the designer of the library wanted a certain kind of access - or that the compiler maybe gave an error at some point when it was “private”?

This is somewhere where I have to bring up my learning and experience with other languages. Albeit only with classes, private always meant what it said on the tin - from outside of a class, it doesn't exist, don't touch!

Which is why I am very wary of reverting file scope to private.

'fileprivate' is a keyword that allows, not extensibility but visibility.

Extensibility control for non-class types is more akin to using or not using 'final' to control inheritance/overriding with classes.

Maybe, instead of looking at extending visibility by adding yet another visibility specifier (extensible), we should be looking at adding a specifier that limits extensibility for any type?

This would be additive and would have the advantage of not breaking so much code.

OK, how does this sound?

Extend the 'final' concept, currently used only in classes, to protect any, non-protocol, type from being extended.

That way, folks who are not so "purist" about access control can continue as before, leaving those of us who want that control to be able to exercise it.

So, for example :

final struct DontExtendMe

extension DontExtendMe // error : final type cannot be extended

I am not suggesting that 'final' should be applicable to members of non-class types. Members of class types should continue to be markable as 'final' for inheritance control reasons.

Joanna Carter
Carter Consulting

More information about the swift-evolution mailing list