Access Controls in Swift: public, private, fileprivate, and private(set)

Access Controls in Swift: public, private, fileprivate, and private(set)

Access control is an essential feature in Swift that allows you to specify the level of access that parts of your code have to other parts. It helps in encapsulating functionality and protecting sensitive data. Swift provides several access control modifiers, each serving a specific purpose. In this article, we'll explore public, private, fileprivate, and private(set) modifiers in Swift, along with examples demonstrating their usage.

1. public

The public access control modifier allows entities to be accessed from any source file in the same module or from another module that imports the module in which the entity is defined. It is the highest level of access control.

public class MyClass {
    public var publicProperty: Int = 0
    
    public func publicMethod() {
        // Code implementation
    }
}

In the example above, MyClass, publicProperty, and publicMethod are all accessible from any part of the module or from modules that import this module.

2. private

The private access control modifier restricts the use of an entity to the enclosing declaration, such as a type, extension, or function. It ensures that the entity is accessible only within the scope in which it is declared.

class MyClass {
    private var privateProperty: Int = 0
    
    private func privateMethod() {
        // Code implementation
    }
}

In this example, privateProperty and privateMethod are accessible only within the MyClass scope. Attempting to access them from outside MyClass will result in a compilation error.

3. fileprivate

The fileprivate access control modifier restricts the use of an entity to its defining source file. It allows entities to be accessed within the same file in which they are declared, regardless of their type.

fileprivate var fileprivateProperty: Int = 0

fileprivate func fileprivateFunction() {
    // Code implementation
}

In the above code, fileprivateProperty and fileprivateFunction can be accessed from any part of the same source file in which they are declared. However, they are not accessible from other source files within the same module.

4. private(set)

The private(set) access control modifier allows a property to be read from any scope but restricts its write access to within the enclosing type. It provides a convenient way to make a property publicly readable but privately writable.

public class MyClass {
    private(set) var privateSetProperty: Int = 0
    
    public func setPrivateSetProperty(value: Int) {
        privateSetProperty = value
    }
}

In this example, privateSetProperty can be read from any part of the module since it's marked as public, but it can only be modified within the MyClass scope due to the private(set) modifier.

Access Controls: Use Cases and Best Practices

  • public: Use when you want entities to be accessible from any part of the module or from other modules.
  • private: Use when you want to restrict the access of entities to the enclosing declaration.
  • fileprivate: Use when you want entities to be accessible within the same source file but not from other source files in the same module.
  • private(set): Use when you want to expose a property for reading but restrict writing to the enclosing type.

Code Example using private(set):

public class BankAccount {
    private(set) var balance: Double = 0.0
    
    func deposit(amount: Double) {
        balance += amount
    }
    
    func withdraw(amount: Double) {
        if amount <= balance {
            balance -= amount
        } else {
            print("Insufficient funds")
        }
    }
}

// Usage:
let account = BankAccount()
account.deposit(amount: 100.0)
print("Balance:", account.balance) // Accessible
// account.balance = 200.0 // Error: Cannot assign to property: 'balance' setter is inaccessible

In this example, the balance property of BankAccount can be read from any part of the module but can only be modified within the BankAccount class itself.

Access Controls in Swift

Access control in Swift provides a powerful mechanism for encapsulating functionality and protecting data. By using public, private, fileprivate, and private(set) modifiers appropriately, you can ensure that your code is well-organized, secure, and maintainable. Understanding these access control modifiers is crucial for writing robust and scalable Swift code.