Swift OOP
Swift's classes are reference types while structs are value types, and understanding that distinction is the foundation of everything else in Swift's object model.
Classes and Structs
Swift gives you two primary building blocks for modeling data: classes and structs. Both can declare properties, methods, and initializers, and both can conform to protocols, but they behave very differently the moment you assign an instance to a new variable or pass it into a function.
Value Types vs Reference Types
A struct is a value type: assigning it to a new variable, or passing it as a function argument, copies its entire contents. A class is a reference type: assigning an instance to a new variable creates a second reference to the exact same object in memory, so mutating through one variable is visible through the other.
- Structs are copied on assignment and on function calls; classes are shared by reference.
- Structs receive a free memberwise initializer; classes must define their own init or rely on default values.
- Structs cannot inherit from another struct; classes support single inheritance from one superclass.
- Copies of a struct are independent, which makes structs safer to share across threads.
- Classes support identity comparison with the === and !== operators; structs have no notion of identity.
Struct value semantics
struct Point {
var x: Int
var y: Int
}
var a = Point(x: 1, y: 2)
var b = a // b is a full copy of a
b.x = 99
print("a.x = \(a.x)") // a.x = 1 (unchanged)
print("b.x = \(b.x)") // b.x = 99Class reference semantics
class Counter {
var value = 0
}
let c1 = Counter()
let c2 = c1 // c2 points to the same instance as c1
c2.value = 42
print("c1.value = \(c1.value)") // 42, both refer to the same object
print(c1 === c2) // true: same identityInitializers, Computed Properties, and Methods
Both classes and structs can define custom initializers, computed properties that calculate a value on access, and methods that operate on their data. The one difference: a struct method that changes any property must be marked mutating, because struct instance methods otherwise treat self as read-only.
A class with init, computed property, and methods
import Foundation
class BankAccount {
let owner: String
private var balance: Double
init(owner: String, openingBalance: Double = 0) {
self.owner = owner
self.balance = openingBalance
}
var formattedBalance: String {
String(format: "$%.2f", balance)
}
func deposit(_ amount: Double) {
balance += amount
}
func withdraw(_ amount: Double) throws {
guard amount <= balance else {
throw NSError(domain: "BankAccount", code: 1)
}
balance -= amount
}
}
let account = BankAccount(owner: "Priya", openingBalance: 100)
account.deposit(50)
print(account.formattedBalance) // $150.00Exercise: Swift OOP
What is a core difference between a class and a struct in Swift?