Swift 3 Access Control

On August 15th, 2016 Apple has releases Xcode Beta 6. With the new Swift 3 version around the corner it’s time to start studying the changes to the language: Access Control is one of the major changes, especially if you use different modules in your project.

Before diving into Swift 3, let’s have a look at the past and see what we used in Swift 2.2.

Evolution

In Swift 2.2 we have 3 different access levels:

  • public allows access within any source file from their defining module and also in a source file from another module that imports the defining module.
  • internal allows access from any source file in their defining module
  • private allows access from its own source file.

These access levels created some side-effects during development, described in proposals in the Swift Evolution discussion.

SE-0025: Scoped Access Level

The SE-0025 proposal describes 2 problems:

  • If a file already has multiple classes, it is not clear if a particular API is meant to be hidden completely or can be shared with the other classes
  • It forces a one class per file structure, every API in the file share the same access level

This is very limiting, especially if you want to divide one big class in different extensions: if an extension is in a different file, it can’t access private variables of the main class.

SE-0117: Allow distinguishing between public access and public overridability

The SE-0117 proposal describes a problem that modules currently have:

  • If a class/method is declared internal, it can’t be used in external modules
  • If a class/method is declared public, it can be used in external modules but can also be overridden by subclasses, creating some problems for library design

This is very limiting, especially if you want to divide one big class in different extensions: if an extension is in a different file, it can’t access private variables of the main class.

Swift 3 Access Control

These 2 proposals where accepted and are now part of Swift 3: personally I think they are a good improvement for the language itself, giving developers the freedom to create reusable modules and organizing code in a better way.
The result is an improved access control system, that adds new levels and, most important, modifies old levels. Swift has now 5 access levels:

  • open
  • public
  • internal
  • fileprivate
  • private

In a sentence: open > public > internal > fileprivate > private

Open

This is a new Swift 3 access level, it was introduced after the proposal SE-0117: “To allow a class to be externally subclassed or a method to be externally overridden, declare them as open, which is a new access level beyond public“.

Its use is easy while in the same module, but it is interesting if you use it with different modules.

Same module:

  • if a class is declared as open, you can subclass it
  • if a method is declared as open, you can override it

Different module:

  • if a class is declared as open, you can subclass it
  • if a method is declared as open, you can override it if its class is declared as open

A very important point is the changes on the imported Objective-C code: imported Objective-C classes and methods are now all imported as open rather than public.
For the unit tests that import a module using an @testable import nothing will change: they will still be able to subclass public or internal classes and override public or internal methods (loving it ❤️).

Public

With the new open access level around, the public one became more conservative. You won’t notice any difference from the open access level while working in the same module but you will see a big one working with different modules.

Same module:

  • if a class is declared as public, you can subclass it
  • if a method is declared as public, you can override it

Different module:

  • if a class is declared as public, you can’t subclass it
  • if a method is declared as public, you can’t override it

Lower access levels can’t be seen from different modules.

Internal

The internal access level wasn’t modified from Swift 2.2.

  • if a class is declared as internal, you can subclass it
  • if a method is declared as internal, you can override it

Fileprivate

This is a new Swift 3 access level, it was introduced after the proposal SE-0025: “The access level formerly known as private is now called fileprivate.” and it means that Swift 2.2 private = Swift 3 fileprivate.

  • if a class is declared as fileprivate, you can subclass it only in the same file of the superclass
  • if a method is declared as fileprivate, you can override it only if its class is declared in the same file of the superclass

Private

This access level has a new meaning compared to Swift 2: “A declaration marked as private can now only be accessed within the lexical scope it is declared in (essentially the enclosing curly braces {}). A private declaration at the top level of a file can be accessed anywhere in that file, as in Swift 2
So the access depends on where you put the declaration.

Conclusion

This is a great change in the Swift evolution: more access levels mean more control and, for the first time, developers can decide which part of the code can be simply used or overridden.

Happy access levels,
M.