Hidden feature: final


You’re more of a video kind of person? I’ve got you covered! Here’s a video with the same content than this article 🍿


I’m certain you’ve already heard of the keyword final.

When you use this keyword on a class or on a method, it makes it impossible to subclass or to override.

But did you know that final also has a hidden feature?

Let’s take the example of this ViewController:

This ViewController implements three different methods.

And it’s possible for any subclass of this ViewController to override these methods:

As a consequence, whenever one of these methods is called, Swift will need to dynamically dispatch the call at runtime, in order to identify the correct implementation.

And of course, this dynamic dispatch has a cost in performance.

Now let’s see what happens if we mark ViewController as final.

Because ViewController is now final, the compiler knows that it’s impossible to create a subclass that would override some of its methods.

This means that for all the methods that are not already overridden, the compiler will know for certain at compile time which implementation to call!

And so the compiler will be able to optimize the call sites, because it won’t need to perform a dynamic dispatch anymore.

Of course, taken individually each of these optimizations will only slightly improve the performances.

But at the scale of an entire project, they can quickly add up to the point where it starts to make a difference!

By the way, if you enable the build option “Whole Module Optimization”, then the compiler will even be able to automatically infer the keyword final in some situations.

Check out this article from the Swift team for more details on this!

That’s all for this article, I hope you’ve enjoyed learning this new trick!

Here’s the code if you want to experiment with it:

final class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // ...
    }

    func firstMethod() {
        // ...
    }

    func secondMethod() {
        // ...
    }
}
Previous
Previous

Discover the advanced features of Xcode’s breakpoints 🐛

Next
Next

How to write tests that detect memory leaks 💦