Encapsulation in Swift


In Swift, encapsulation is one of the fundamental principles of Object-Oriented Programming (OOP) that focuses on hiding the internal details of a class and exposing only what is necessary. It allows grouping related properties and methods into a single unit (class or struct) and restricts direct access to some of the object's components, which protects the integrity of the data.

Encapsulation improves security, prevents unauthorized access, and makes the code easier to maintain. Swift achieves encapsulation using access control modifiers like private, fileprivate, internal, public, and open.

Key Points to Remember

  • Encapsulation binds data (properties) and methods that operate on the data into a single unit.
  • It helps hide internal data of an object and restricts access using access modifiers.
  • The private keyword prevents properties and methods from being accessed outside the class.
  • Setter and getter methods (computed properties) can be used to control how data is accessed and modified.
  • Encapsulation leads to better control, security, and reduced complexity in code.

Syntax

class ClassName {
     private var propertyName: DataType

     init(propertyName: DataType) {
         self.propertyName = propertyName
    }

     func getPropertyName() -> DataType {
         return propertyName
    }

     func setPropertyName(value: DataType) {
        propertyName = value
    }
}

Example 1: Encapsulation Using Private Properties and Public Methods

Let's demonstrate how to encapsulate data in a Swift class.

import Foundation

class BankAccount {
     private var balance: Double = 0.0

     func deposit(amount: Double) {
         if amount > 0 {
            balance += amount
             print("Deposited: \(amount)")
        } else {
             print("Invalid deposit amount")
        }
    }

     func withdraw(amount: Double) {
         if amount <=b alance {
            balance -= amount
             print("Withdrawn: \(amount)")
        } else {
             print("Insufficient balance")
        }
    }

     func getBalance() -> Double {
         return balance
    }
}

let account = BankAccount()
account.deposit(amount: 1000)
account.withdraw(amount: 500)
print("Current Balance: \(account.getBalance())")

Output

Deposited: 1000.0
Withdrawn: 500.0
Current Balance: 500.0

Example 2: Encapsulation with Computed Properties

Swift also allows encapsulation using computed properties that control access to private properties.

import Foundation

class Person {
     private var _age: Int = 0

     var age: Int {
         get {
             return _age
        }
         set(newAge) {
             if newAge >= 0 {
                _age = newAge
            } else {
                 print("Invalid age")
            }
        }
    }
}

let person = Person()
person.age = 25
print("Person's age: \(person.age)")

person.age = -5 // Invalid age, won't be set
print("Person's age: \(person.age)")

Output

Person's age: 25
Invalid age
Person's age: 25

Example 3: Encapsulation with Fileprivate Access Modifier

The fileprivate access modifier restricts access to the same file, which is useful when related classes are defined in the same file.

import Foundation

class Employee {
     fileprivate var salary: Double = 5000.0

     func displaySalary() {
         print("Salary: \(salary)")
    }
}

class Manager: Employee {
     func increaseSalary() {
        salary += 2000
    }
}

let manager = Manager()
manager.increaseSalary()
manager.displaySalary()

Output

Salary: 7000.0