Last year, I wrote about the difference between private and fileprivate in Swift 3. With the impending release of Swift 4, it's time for an update. Access control underwent several important changes since the introduction of the Swift language, several years ago.

Swift 3 added the fileprivate keyword. An entity that is declared fileprivate is only accessible from within the file it is defined in. What's more important is that the addition of the fileprivate keyword also changed the meaning of the private keyword.

What Has Changed

The change is easy to understand and, more importantly, very focused. The primary criticism of the changes to access control wasn't the introduction of the fileprivate keyword. It were the consequences fileprivate had on the meaning of the private keyword. The fileprivate keyword took over the role of the private keyword and the latter became more restrictive.

Even though many developers asked for the removal of the fileprivate keyword, the Swift team came up with an alternative that only modified the meaning of the private keyword. In other words, the meaning of the fileprivate keyword remains unchanged in Swift 4. But to understand what changed, you need to understand the meaning of the private keyword in Swift 3.

Private in Swift 3

The meaning of the private keyword in Swift 3 is simple. This is how The Swift Programming Language defined private access in Swift 3.

Private access restricts the use of an entity to the enclosing declaration. Use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.

This means that you can't reach across to a private declaration from another lexical scope. Take a look at this example to better understand what that means.

import UIKit

class NotesViewController: UIViewController {

    private var dataSource = [String]()

}

extension NotesViewController: UITableViewDataSource {

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return dataSource.count
    }

    ...

}

It's become a common practice to split the implementation of a type up by leveraging extensions. In this example, we use an extension for the NotesViewController class to implement its conformance to the UITableViewDataSource protocol.

Even though Swift 3 supports this use of extensions, it's only possible if (1) we declare the dataSource property fileprivate and (2) the extension for the NotesViewController class lives in the same source file as the declaration of the type. This isn't a major issue, but there's room for improvement.

What Is the Difference Between Private and Fileprivate in Swift 4

Private in Swift 4

The Swift team decided against the removal of the fileprivate keyword and the reversal of the stricter meaning of the private keyword. They came up with a better solution that facilitates the compatibility of Swift 3 and Swift 4.

In Swift 4, the implementation of the private keyword is slightly altered. Let's revisit the example I showed you earlier. In Swift 4, an extension can reach across to a private declaration. This only applies to extensions that live in the same source file as the private declaration.

In other words, an entity that is declared private is accessible from within any extensions for that type within the same source file. Swift 4 slightly expands the scope of what private means to facilitate the use of extensions.

Limitations

It's important to emphasize that extensions can only reach across to a private declaration if the extension and the declaration live in the same source file. In other words, the private keyword remains more restrictive than the fileprivate keyword. And that's a good thing.

What Do We Gain

You may be wondering why this is important. You can declare the dataSource property fileprivate. That solves the problem too. Right? That's true, but it also means that the dataSource property is accessible by any entity in the source file the dataSource property is declared in.

While this is a subtle detail, I appreciate the change and the attention to detail of the Swift team and the Swift community. It's details like this that make the Swift language intuitive, elegant, and a joy to use.

We're still in a phase that allows us, the Swift community, to make changes like this. We strive towards a language that's robust, modern, and elegant. That means we need to make changes and tweak the language as it evolves and is used by more people.

Is This Better?

Is this better? It certainly is and I'm sure most Swift developers feel the same way. You can read the details of this change on GitHub. Proposal SE-0169 goes into the details, changes, and motivation for the change.

Soon after the introduction of the Swift language, developers started using extensions to break the implementation of types up into logical components. This has become a common practice and is even referred to as good Swift coding style by Doug Gregor, a member of Apple's Swift team. It is nice to see that the Swift language evolves and adapts to make best practices intuitive and painless to adopt.