The open keyword in Swift: what it is and why beginners need it

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

What does the open keyword in Swift hide? A breakdown for beginners



Have you ever written a class in Swift, added public to it, and then tried to inherit from it in another module — only to get a compilation error? If so, you are not alone. This question is one of the most popular on Stack Overflow among beginner Swift developers. Thousands of people stumble over the same stone: the open keyword.



In this article, we will finally figure out what open is in Swift, how it differs from public, when you need to use it, and when you absolutely should not. We will write real code, look at errors, and learn how to fix them. Let's go!



The access modifier system in Swift: a quick primer



Before diving into open, let's recall what access levels exist in Swift. There are five (from the most restrictive to the most open):



  • private — accessible only within a single file and a single declaration (e.g., inside a class).
  • fileprivate — accessible within the entire file.
  • internal — accessible within the entire module (this is the default level).
  • public — accessible from other modules, but cannot be inherited or overridden.
  • open — accessible from other modules, can be inherited and overridden.


The main intrigue lies in the difference between public and open. At first glance, they are similar: both allow accessing a class, method, or property from another module. But there is one fundamental difference, which we will now break down with examples.



Example: a public class that cannot be extended



Imagine you are writing a library (framework) for working with the network. You create a class NetworkService and make it public:



// Module: MyNetworkingFrameworkpublic class NetworkService {    public func fetchData() {        print("Fetching data from network...")    }}


Now another developer imports your framework and wants to create their own improved class based on it:



// Module: MyAppimport MyNetworkingFramework

// Error! Cannot inherit from a public classclass MyNetworkService: NetworkService { override func fetchData() { print("My custom fetching...") }}


The compiler will throw an error. Why? Because public is read-only access from another module. You can use an instance of the class, call its methods, but you cannot inherit from it. This is intentional: the library author wants to control which classes can be extended and which cannot.



Solution: use open



If the library author wants to allow inheritance, they must explicitly specify open:



// Module: MyNetworkingFrameworkopen class NetworkService {    open func fetchData() {        print("Fetching data from network...")    }}


Now, in another module, you can freely inherit and override methods:



// Module: MyAppimport MyNetworkingFramework

class MyNetworkService: NetworkService { override func fetchData() { print("My custom fetching with extra logging...") super.fetchData() }}


That's the whole magic. The open keyword is permission for inheritance and overriding outside the module.



Why is open important for architecture?



Swift and Apple developers did not introduce this distinction for no reason. It helps design stable and safe APIs. Imagine you release a library, and all classes in it are open.

Blogs

Book Recommendations