Swift Classes

Object-oriented programming with reference types

🏗️ What are Swift Classes?

Classes are reference types that define blueprints for creating objects. They support inheritance, method overriding, and shared instances. Classes are perfect for modeling complex entities with shared behavior and state.


// Basic class definition
class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    func greet() {
        print("Hello, I'm \(name)")
    }
}

let person = Person(name: "Alice", age: 30)
person.greet() // Output: Hello, I'm Alice
                                    

Key Class Features

🔗

Reference Types

Classes are passed by reference

let person1 = Person(name: "Bob", age: 25)
let person2 = person1
person2.name = "Robert"
print(person1.name) // "Robert"
🧬

Inheritance

Classes can inherit from other classes

class Student: Person {
    var studentID: String
    
    init(name: String, age: Int, id: String) {
        self.studentID = id
        super.init(name: name, age: age)
    }
}
🔧

Initializers

Custom initialization methods

class Car {
    let brand: String
    var speed: Int = 0
    
    init(brand: String) {
        self.brand = brand
    }
}
🗑️

Deinitializers

Cleanup when instances are deallocated

class FileManager {
    deinit {
        print("Cleaning up resources")
    }
}

🔹 Basic Class Example

Here's a simple class with properties and methods:

class BankAccount {
    var accountNumber: String
    var balance: Double
    
    init(accountNumber: String, initialBalance: Double = 0.0) {
        self.accountNumber = accountNumber
        self.balance = initialBalance
    }
    
    func deposit(amount: Double) {
        balance += amount
        print("Deposited $\(amount). New balance: $\(balance)")
    }
    
    func withdraw(amount: Double) -> Bool {
        if amount <= balance {
            balance -= amount
            print("Withdrew $\(amount). New balance: $\(balance)")
            return true
        } else {
            print("Insufficient funds")
            return false
        }
    }
}

let account = BankAccount(accountNumber: "12345", initialBalance: 100.0)
account.deposit(amount: 50.0)
account.withdraw(amount: 30.0)

Output:

Deposited $50.0. New balance: $150.0

Withdrew $30.0. New balance: $120.0

🔹 Class Inheritance

Classes can inherit properties and methods from parent classes:

class Vehicle {
    var brand: String
    var year: Int
    
    init(brand: String, year: Int) {
        self.brand = brand
        self.year = year
    }
    
    func start() {
        print("\(brand) is starting...")
    }
}

class Car: Vehicle {
    var numberOfDoors: Int
    
    init(brand: String, year: Int, doors: Int) {
        self.numberOfDoors = doors
        super.init(brand: brand, year: year)
    }
    
    override func start() {
        print("Car engine starting...")
        super.start()
    }
    
    func honk() {
        print("Beep beep!")
    }
}

let myCar = Car(brand: "Toyota", year: 2023, doors: 4)
myCar.start()
myCar.honk()

Output:

Car engine starting...

Toyota is starting...

Beep beep!

🔹 Computed Properties

Classes can have computed properties that calculate values:

class Rectangle {
    var width: Double
    var height: Double
    
    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }
    
    var area: Double {
        return width * height
    }
    
    var perimeter: Double {
        return 2 * (width + height)
    }
    
    var isSquare: Bool {
        return width == height
    }
}

let rect = Rectangle(width: 5.0, height: 3.0)
print("Area: \(rect.area)")
print("Perimeter: \(rect.perimeter)")
print("Is square: \(rect.isSquare)")

let square = Rectangle(width: 4.0, height: 4.0)
print("Square area: \(square.area)")
print("Is square: \(square.isSquare)")

Output:

Area: 15.0

Perimeter: 16.0

Is square: false

Square area: 16.0

Is square: true

🔹 Class vs Struct

Understanding when to use classes vs structures:

Use Classes When:

  • Inheritance: You need to inherit from another class
  • Reference semantics: Multiple variables should refer to the same instance
  • Identity: You need to check if two instances are identical (===)
  • Deinitializers: You need cleanup when instances are destroyed

Use Structs When:

  • Value semantics: Each instance should be independent
  • Simple data: Modeling simple data without complex behavior
  • Thread safety: Value types are safer in concurrent code
  • Performance: Structs can be more efficient for small data

🧠 Test Your Knowledge

What type of type are Swift classes?