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