Swift Access Controls are like C's (and that isn't necessarily a bad thing)

Apple introduced access controls to Swift with the release of Xcode 6 Beta 4 and accompanying documentation (revision history).. The approach they have taken contrasts strongly with that taken by languages like C++, C# and Java in that the controls do not limit access based on the class hierarchy but instead limit based on the file and module.

Even variables declared private can be accessed from other classes and functions that reside within the same file. This allows properties and functions to be declared private but still accessible to free functions and operators defined particularly to operate with that class. It avoids some of the complexity that has C++ having "friend" classes and functions.

Swift Access Controls

The iBook hasn't been updated to match Beta 4 yet but The iBook was updated shortly after this post was written and the online version is updated with full access control information. I'm going to describe the effect of the different modifiers but not the way you can combine them or apply them to particular declarations. If you want those details please look at the official documentation.

internal

This is actually the default access level and means that the class/variable/type is available from all files within the same framework (or from anywhere within the application if that is what you are writing).

The C equivalent is variables and structures defined within internal project header files. Well structured C projects have normally had a header (.h) file for each source (.c) file but these header files were only meant to be imported by from within the project.

private

The most restrictive level of control limits the access to the variables/classes/types to only be accessed from within the same file.

The C equivalent would be variables and structures declared within the .c file and not exposed in any header files.

public

These are the functions/classes/types that are exposed to client libraries. Only things defined with this access modifier are available to clients of the framework. This forms the public API to your framework. Things defined as public are also pulled into a header file which is exposed and forms the interface particularly for Objective C/C code to import and access the library with.

The equivalent in C is to manually create a public header for a library exposing the public API necessary to use the library.

Where is "protected"?

There is no "protected" modifier. In Swift you get no special access to classes that you inherit from. This means that the access modifiers are not suitable or helpful for creating abstract classes. At this time (Beta 4) there is no mechanism to enforce that subclasses must implement particular methods or to prevent a class that you want to abstract from being created.

Does You Need Abstract Classes?

Discussion on the forums seems to weigh towards most people thinking that while Abstract classes may be overused in Java but they are generally a good option to have. However, this is something that I'm not yet sure about.

Most of the Apple libraries use delegates to customise behaviour without having to subclass. There are exceptions one of which was raised as an example is the UIGestureRecognizer class. As it stands Apple provides several concrete subclasses but you can actually create your own recognizer by subclassing UIGestureRecognizer. The UIGestureRecognizer already has a delegate that receives the messages but instead of subclassing I think that it could have been designed so that it required a second delegate to process the touches and respond to recognised(I'm British and I'm going to spell properly) gestures. You could still subclass UIGestureRecognizer and specialise it by fixing the recognition delegate (possibly as self) within the subclass.

The fact that you can do without abstract classes doesn't necessarily mean that you are better off without them (and this is the area where I'm not confident). Generally abstract classes mix the requirements of implementing a protocol and how it should be implemented by requiring the subclassing so I think I'm leaning towards discouraging them in Swift.

There are other mechanisms than the access controls that could be used to support Abstract classes and I don't know if Chris Lattner and the Apple team are planning to add them. Examples could be indicating with a keyword that particular methods (possibly including initialisers) must be overridden.


Update (20th August 2014) - Apple have a new blog post that responds to the requests for protected and largely dismisses them.

What Else Aren't People Happy With?

One of the issues that has been raised on the forum is that frameworks aren't the right level to break the automatic inclusion on especially since unlike in C everything is automatically imported within the framework. I'm fairly ambivalent on this. The answer might be to develop with lots of fairly small frameworks and if Apple makes it easy enough to divide the code into frameworks it might not be a problem. My iOS apps have been developed as a solo developer (I have worked on major C++ projects in the past) so I'm not sure whether this would work well or have problems. It would certainly be a change in style for most iOS projects but with the improved support for Frameworks I think that it could work really well. I would be interested to hear what others think about this and whether an intermediate module level would be worthwhile.

Is Swift and Object Oriented Language?

I might make a separate post soon to go into more details but I would describe Swift as a language that supports both Functional, Imperative and Object Oriented approaches. I think that the way the access controls are implemented is an indicator (along with others) that objects and classes are not on a pedestal over other approaches. The access control approach that they have used is one that is fully usable without objects and classes.

At the moment lots of people are writing Swift code in the same object orientated way as they wrote Objective-C code but with stricter type checking and nicer syntax. I think it will be very interesting to learn from Haskell and ML developers how to develop in other ways to fully exploit the power of Swift and how to combine them with object oriented and imperative code. I'm going to buy the Functional Programming in Swift book the objc.io guys are writing and see if it inspires me.

Summary of Open Questions on my Mind

  • Are protected methods needed?
  • Are abstract classes a good approach in Swift or are delegates a better approach?
    • Do they need language support?
  • Should code be split into small Frameworks?
    • Is there a strong need for modules or directory/group based access rather than full access across a whole Framework?
  • How do I really incorporate Functional techniques and immutable data?

If you have any answers, comments, questions feel free to comment or email me directly. My email address is on the main Human Friendly site.

7 responses
I disagree. While I can see that protected and abstract can cause some confusion, they are extremely good for creating a rigid framework for some well established Object Oriented Design Patterns like "Template Method". These are well engineered, well understood and industry standard patterns for creating software and Apple actually use slightly crippled versions of them in their own frameworks. By removing these keywords from the language they open such class structures to abuse or misuse meaning as a framework author you have to put in strongly worded comments/documentation to hope people use your code correctly or (as I do) put runtime asserts in base class methods to make the coder override them, which is a crude hack. Apple in that blog post gloss over the "two cases" where protected/abstract are needed and they don't provide a good answer to how to deal with those two cases. To take this approach to its logical conclusion you could say "Why have any encapsulation? Just document the methods in the class you're supposed to use and the ones you're not supposed to use!" :)
Hi Carl, I still don't see particular advantages of that approach over delegation. Define a protocol with the methods you need to call and make your class's init require a delegate. You can then call those methods on the delegate rather than on self. Then make anything that you don't want open private. My view that (implementation) inheritance makes most things worse is strengthening these days rather than weakening and showing explicitly what needs to be implemented (the delegate protocol) prevents no hiding that you want in place. Maybe you could make a gist of something that you would like to do in Swift but can't and I might see what I'm missing.
It's not that you cannot do these patterns in Swift, it's that you are fighting to do them and the language makes it hard, which is a shame. I'm aware of the whole composition is better than inheritance mantra and I think it's a very good thing to consider (inheritance was overused in the early days of OO) but I think it's not always right. I've already given an example in the first comment, the Template Method design pattern. While you can force this into delegation, it would be a very unnatural fit. (For readers who are not familiar with it the pattern has an elegant structure where you create a method or methods with the shared code in the base class that calls out to subclasses in some places. You have the flexibility of either keeping shared code in the base class, creating abstract methods that must be overridden or creating methods with a base implementation that may be overridden in special cases.) At the moment I'm writing a base class that handles media storage, upload, download, creating thumbnails, in-memory caching and asynchronous queues to keep it all performant. I'm making this by refactoring a Photo class into a Media base class and creating a new Video subclass of Media. Much of the code and methods will move naturally into the base class and there will be a few places where the behaviour will differ, where a base class method to be overridden is perfect (makeThumbnail, placeholderImage, etc.) To use delegation in this case would be a rather unnatural fit. Semantically and in my code, a photo is a type of media, so is a video. This means then I can create arrays of media, use polymorphism, etc. without having to create a new protocol that all media conform to. It makes a simpler, cleaner and more readable class structure. (I'm afraid I probably can't post the code partly because it's still completely unfinished and partly because I am probably obliged to keep it confidential.) I think there has been a proliferation of cool languages with weak OO and as a result OODP has been incorrectly denigrated as "an old technique". I think sometimes delegation is a great fit for the problem and sometimes it really isn't. There's a reason why Java, C# and C++ all have these keywords and if Swift is to be a language that covers all cases then I think it will need to have at least a modified version of these concepts. In much the same way that they added try...catch error handling. In fact I'll stick my neck out and say that I bet they will add something like these keywords within the next few years. It will be fun to see. :)
You might be right that these features will be added to Swift at some point but especially with Swift 2 protocols are really great and powerful (although still not quite where I want) and provide the answer in many cases. In a case like yours (which fits OO better than most) I would not just have one delegate protocol but multiple. e.g. CustomImageProvider (that would probably cover placeholders and thumbnails), and other protocols for other aspects. The "base" class can then have settable properties for all the customisable aspects. If the property is nil then the default implementation kicks in. One advantage of this is that you don't end up with big classes as different objects can handle the different delegate aspects rather than having a single big class. Another is that the implementation of a protocol may be reused for different media types even when they are not natural subclasses of each other.
One extra advantage is that protocols allow the client developer to subclass the main object (and implement all the protocols setting the delegates to self) but they also allow different implementations if they prefer. In your specific example how do you handle aggregated media types (multi track multi content type objects). Does it subclass video and get to use the thumbnail generation from the video class, what about the audio. With protocols easily configured but not obvious with inheritance for me.
2 visitors upvoted this post.