Swift Classes

A class is a blueprint for creating objects that share a reference. Unlike a struct (which creates independent copies), a class creates a single object that multiple variables can point to simultaneously. Think of a class instance like a shared Google Doc — any person who has the link sees and edits the same document.

Defining a Class

class Car {
    var brand: String
    var speed: Int

    init(brand: String, speed: Int) {
        self.brand = brand
        self.speed = speed
    }

    func describe() {
        print("\(brand) going \(speed) km/h")
    }
}

let myCar = Car(brand: "Tesla", speed: 100)
myCar.describe()   // Output: Tesla going 100 km/h

Classes require a manual init method. Unlike structs, Swift does not generate one automatically when you have stored properties without default values.

Classes Are Reference Types

When you assign a class instance to a new variable, both variables point to the same object. A change through one variable is visible through the other.

let carA = Car(brand: "BMW", speed: 120)
let carB = carA        // Both point to the SAME object

carB.speed = 200

print(carA.speed)   // Output: 200 (carA also changed!)
print(carB.speed)   // Output: 200

Diagram: Reference Type vs Value Type

STRUCT (Value Type)              CLASS (Reference Type)
var a = Point(x:1)               let a = Car(brand:"BMW")
var b = a                        let b = a
  [a: x=1]  [b: x=1]                 [a] ──┐
  (two boxes)                          [b] ──┤──→ [ Car object ]
                                            └──   (one object)
b.x = 9 → only b changes         b.speed = 200 → both a and b see it

Identity Operators

Use === to check if two variables point to the exact same object (not just equal values).

let c1 = Car(brand: "Audi", speed: 150)
let c2 = c1
let c3 = Car(brand: "Audi", speed: 150)

print(c1 === c2)   // true  — same object
print(c1 === c3)   // false — different objects with same values
print(c1 !== c3)   // true  — not the same object

Deinitializer

A class can define a deinit method that runs automatically when the object is about to be destroyed and removed from memory.

class Session {
    let id: Int

    init(id: Int) {
        self.id = id
        print("Session \(id) started.")
    }

    deinit {
        print("Session \(id) ended.")
    }
}

var s: Session? = Session(id: 42)
// Output: Session 42 started.
s = nil
// Output: Session 42 ended.

Class Properties and Methods

Classes support stored properties, computed properties, and methods just like structs — but without the mutating keyword requirement.

class BankAccount {
    var owner: String
    private var balance: Double

    init(owner: String, initialBalance: Double) {
        self.owner = owner
        self.balance = initialBalance
    }

    func deposit(amount: Double) {
        balance += amount
        print("Deposited \(amount). New balance: \(balance)")
    }

    func withdraw(amount: Double) {
        guard amount <= balance else {
            print("Insufficient funds.")
            return
        }
        balance -= amount
        print("Withdrew \(amount). New balance: \(balance)")
    }

    func showBalance() {
        print("\(owner)'s balance: \(balance)")
    }
}

let account = BankAccount(owner: "Alice", initialBalance: 500.0)
account.deposit(amount: 200.0)    // Deposited 200.0. New balance: 700.0
account.withdraw(amount: 100.0)   // Withdrew 100.0. New balance: 600.0
account.showBalance()             // Alice's balance: 600.0

Access Control

Use access modifiers to control what is visible outside the class.

ModifierVisible To
openAny module, subclassable outside
publicAny module
internalSame module (default)
fileprivateSame file only
privateSame class only

Type Properties and Methods

Use class keyword (not static) for type-level methods that subclasses can override.

class Vehicle {
    class func describe() {
        print("I am a vehicle.")
    }
}

class Truck: Vehicle {
    override class func describe() {
        print("I am a truck.")
    }
}

Vehicle.describe()   // Output: I am a vehicle.
Truck.describe()     // Output: I am a truck.

Struct vs Class — Quick Reference

FeatureStructClass
TypeValueReference
CopyingIndependent copyShared reference
InheritanceNoYes
deinitNoYes
Automatic initYes (memberwise)No (must write it)
Mutating keywordRequiredNot needed

Summary

Classes create reference-type objects where multiple variables share the same instance. Use === to test object identity. Add deinit to clean up resources when an object is released. Prefer structs for simple data models and reach for classes when you need inheritance or shared state.

Leave a Comment

Your email address will not be published. Required fields are marked *