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/hClasses 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: 200Diagram: 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 objectDeinitializer
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.0Access Control
Use access modifiers to control what is visible outside the class.
| Modifier | Visible To |
|---|---|
open | Any module, subclassable outside |
public | Any module |
internal | Same module (default) |
fileprivate | Same file only |
private | Same 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
| Feature | Struct | Class |
|---|---|---|
| Type | Value | Reference |
| Copying | Independent copy | Shared reference |
| Inheritance | No | Yes |
| deinit | No | Yes |
| Automatic init | Yes (memberwise) | No (must write it) |
| Mutating keyword | Required | Not 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.
