[swift-evolution] [Proposal] Protected Access Level

Callionica (Swift) swift-callionica at callionica.com
Sun May 29 18:26:37 CDT 2016


I can't reply directly to all the points in this thread, but I will just
say that there are ways of emulating protected in the language as it exists
today:

If the goal is to have functions that can be overridden by subclasses
without being called by external classes, you can create a parameter of a
public type with a private initializer and use it in all "protected" member
functions. No external code will be able to call such functions because
they cannot create an argument of the correct type.

If external classes need to both override and call the "protected" members,
you'll need to arrange to pass the key to derived classes which you can do
by taking a function as an argument to the base class initializer. The base
class then calls the function to pass the key to the derived class. This
way only parties that are able to control the function passed to the
initializer are able to obtain the key necessary to call the "protected"
member functions.

You can produce a lot of different access control mechanisms using the same
idea.

I'll write something up at http://www.callionica.com/developer in the next
day or so

-- Callionica

On Sun, May 29, 2016 at 2:55 PM, Vanderlei Martinelli via swift-evolution <
swift-evolution at swift.org> wrote:

> Thank you all for your comments. :-)
>
> Well... My goal is to keep the thing really simple and do not start a new
> "OOP x POP" (or "something" x "other thing") war.
>
> "Protected" access level is not a new concept at all (except for the Swift
> language), so I did not propose anything preposterous.
>
> Of course in the Swift of my dreams we also have "abstract" access level
> modifier, "protected" access level, *real* "private" access level and
> "file" access level modifier (along with many, many other things, of
> course). But this proposal is not about this. It is only about include the
> "protected" access level.
>
> There is, however, something that I need to get off my chest: I really
> would like to have the freedom to go to the depths with protocols as well
> with classes. I work in real apps everyday that uses Cocoa frameworks
> (based on classes) and these apps must be shipped and I like them well
> written. Maybe am I insane for proposing a better support for classes in
> Swift? If so, this explains why every time I suggest better support for
> classes in Swift there is an endless discussion and someone proclaims the
> death of OOP and is it. OK... Maybe someday we will not have more classes
> in Swift. Until there: the current language status is the best way to
> handle OOP in Swift? Or is there a better way? I think there is.
>
>
> Regards,
>
> Vanderlei Martinelli
>
>
>
>
>>
>>
>
> On Sat, May 28, 2016 at 7:52 PM, Vanderlei Martinelli <
> vmartinelli at alecrim.com> wrote:
>
>> Hello.
>>
>>
>> This is the first draft. I'd like to know your opinion about it.
>>
>> (I know that this subject could have been discussed before. If so, please
>> indicate me the correct thread to follow and interact.)
>>
>>
>> Regards,
>>
>> Vanderlei Martinelli
>>
>>
>> ---
>>
>>
>> Introduction
>>
>> Protected access level will enable entities to be used within the
>> container type and by derived types only.
>> Motivation
>>
>> Today Swift has three access levels (public, internal and private), but
>> lacks a way to describe a member that can be only visible to its type or
>> derived types.
>>
>> A common case is the UIView from UIKit. Many developers are tempted to
>> make this call:
>>
>> view.layoutSubviews()
>>
>> The documentation says: "You should not call this method directly. If you
>> want to force a layout update, call the setNeedsLayoutmethod instead to
>> do so prior to the next drawing update. If you want to update the layout of
>> your views immediately, call the layoutIfNeeded method."
>>
>> But yes, you should call this method directly if you are subclassing the
>> view and needs to perform additional layout to its subviews ("subclasses
>> can override this method as needed"):
>>
>> public override func layoutSubviews() {
>>     // We are calling the super method directly here.
>>     super.layoutSubviews()
>>
>>     // Do more adjustments to this view's subviews...}
>>
>> So, yes, we can call this method directly when subclassing, but the Swift
>> compiler will not prevent you from do this when not subclassing or from any
>> other foreign class. It will not even issue a warning.
>>
>> In Objective-C problems like this are usually "solved" my adding a kind
>> of "protected" header (.h) that is intended to be included only when the
>> developer is subclassing. In Swift we do not have headers, but we have the
>> new access level model. So, if the declaration of this method was...
>>
>> protected func layoutSubviews()
>>
>> ... no one outside the class or derived classes would be allowed to call
>> this method directly.
>>
>> Of course, there are other cases in the Cocoa frameworks and there are
>> many other cases when we are developing software in Swift that the
>> protected access level would be very usefull.
>> Proposed solution
>>
>> Create the protected access level.
>> Detailed designReference Types (classes)
>>
>> When declarated by a class the protected member will be visible to the
>> class itself and all the derived classes.
>>
>> // BaseClass.swiftpublic class BaseClass {
>>     public protected(set) var x = 20
>>     protected let y = 10
>>
>>     protected func doSomething() {
>>         // ...
>>     }}
>> // DerivedClass.swiftpublic class DerivedClass: BaseClass {
>>     protected override doSomething() {
>>         self.x = 10 * self.y
>>     }}
>>
>> If the member is declared as final then it will be visible but not can
>> be overrided by the derived classes. Just like it works with other access
>> levels.
>> Value Types (structs, enums, etc.)
>>
>> Value types cannot have derived types. In this case the protected access
>> level does not make sense and will not be allowed in their members.
>> Protocols
>>
>> Protocols do not declare access level for their members. So the protected access
>> level is not applicable here.
>> Extensions
>>
>> Extensions will not be able do be protected nor their members.
>> Special Note
>>
>> The protected access level can only be applied to classes, structs and
>> other types when nested inside other type. So the following code will not
>> compile:
>>
>> // ERROR: A first level class cannot be protected.
>> protected class MyProtectedClass {
>>     /// ...}
>>
>> But nested declarations will be allowed, so this code will compile:
>>
>> // We can declare a protected class (or struct, enum, etc.) if// and only if they are nested inside other type.public class MyPublicClass {
>>     protected class MyProtectedClass {
>>         /// ...
>>     }}
>> // Since `MyProtectedClass` is nested and protected we// can have access to it here.public class MyDerivedClass: MyPublicClass {
>>     public func doSomething() {
>>         let c = MyProtectedClass()
>>
>>         /// ...
>>     }}
>>
>> Impact on existing code
>>
>> The imported Cocoa frameworks may have annotations on the "Objective-C
>> side" that will inform if one member is protected. If this will be case
>> (for the layoutSubviews method, as example), only code accessing these
>> now protected members outside the owner class and its derived classes will
>> have to change (currently this can be considered an error, anyway).
>>
>> Any other code will be not impacted by this feature as it is new to the
>> language.
>> Alternatives considered
>>
>> Do not add the protected access level to the current model.
>>
>>
>> ---
>>
>>
>>
>>
>>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160529/bc5eeb3b/attachment.html>


More information about the swift-evolution mailing list