[swift-evolution] SE-0025: Scoped Access Level, next steps
joanna at carterconsulting.org.uk
Mon Mar 28 11:23:48 CDT 2016
If I may be so bold, as a programmer with over 25 years of experience, in multiple languages…
Although I can see the reasoning behind "redefining" visibility scope for Swift, I find myself both agreeing and disagreeing with various aspects.
Apart from Delphi, I've never come across a use of private other than for the scope of the immediate class only. Delphi does a similar thing to Swift, in that it defines "private" as meaning the scope of the declaring code file until Delphi 7, when someone decided it was a good idea (possibly due to user requests) to add "strict private" to indicate a "true" private member, visible only to the declaring class.
Likewise, at the same time, "strict protected", was added to convey visibility only to inherited classes, in addition to "protected", which means roughly the same as "private". Thus giving Delphi, in order of visibility, "strict private", "strict protected", "private", "protected" and "public". There are even ungodly hacks that allow you to access the private fields of a class in another unit!!!
However, in Swift, we can declare a lot more types as "private", but "protected" really doesn't seem to make sense outside of classes, as there is no inheritance for other types like structs and enums.
But, in Swift, we now have the concept of extensions on all types, making inheritance less necessary and prompting us towards protocol-based programming, where behaviours can be added to any number of types without having to limit that type's inheritance from a base type. Now we can define behaviours that can apply to classes, structs, enums and, even, basic types such as Int and String.
Take the example of the Visitor Pattern : With strictly typed and statically compiled languages, this classically ends up with a system of double dispatch between a hierarchy of classes and a hierarchy of visitors.
Objective-C's class categories permit the extension of a class's behaviour without the Visitor Pattern but, with danger of dynamic dispatch that a "visitation" method may be called when it does not exist in the category. Another problem being that categories can only access "public" members of the main class because "public" is the only visibility Objective-C understands outside of iVars.
Swift's extensions permit the extension of most types (not just classes) so that they can implement one or more protocols, ensuring that the protocol(s) is/are fully implemented by raising a compiler error if not satisfied.
So, if we are going to bring in visibility specifiers to Swift, with all of its wonderful, type-safe, statically compiled code, we have to carefully consider, not just the names of the planned scopes but what impact any restrictions may have on the use of protocol-oriented programming and the various extensions on types that it will engender.
C++ uses the concept of marking certain methods and classes as "friend", so that nominated classes have privileged access to otherwise private members of a class; maybe this is a worthwhile concept for determining what parts of a type can be accessed by an extension?
I am not suggesting "friend" as a name but the need for being able to restrict or allow access to certain members of a type when extending it?
In the light of the preceding paragraphs, I would, respectfully, suggest that "protected" should be allowed for exclusive use in the case of classes that really have to derive from each other, but for no other reason. Likewise, "private" should mean what it has meant and still means in most other languages, members of classes only, since, like "protected", that is its true nature.
What Swift presently calls "internal" seems to equate more to the C# concept of "internal" and, in my mind, needs no further discussion or change.
Just as I was never happy with the Delphi concept of private and protected members being accessible, not just in the class or its derived types, but also from any code in the same code unit, I feel uneasy about the present definition of the private scope in Swift.
I have seen some horrendous abuses of that privileged access, with the gradual growth of single code units to truly gargantuan proportions, just because someone felt that certain classes needed to violate all the rules of common sense and be able to access each others' private parts (if you'll pardon the vernacular).
If several types really have to be defined in the same unit, then their relationship to each other needs defining far more strictly than just to say that they have total free reign to interfere where they want.
Personally, I would like to see the end of the file based scope and, instead, see more clearly defined "privileged" access between types, even if they are in the same code unit.
Let the naysayers (or even the forsayers) commence :-)
More information about the swift-evolution