Browse Questions
- Prefer composition (a type holds/uses other types to get behavior) when: - The relationship is "has-a" rather than "is-a" (a Car has an Engine, it isn't an Engine) - You need to mix behaviors from…
- View controller containment is the API for embedding one view controller inside another so the child keeps its own lifecycle.
- An iOS app moves through states managed by UIApplicationDelegate (UIKit) or @main + scene lifecycle (SwiftUI/iOS 13+).
- VStack renders all its children immediately.
Answer: Prefer composition (a type holds/uses other types to get behavior) when:
- The relationship is "has-a" rather than "is-a" (a
Carhas anEngine, it isn't anEngine) - You need to mix behaviors from multiple sources (single inheritance can't do this; protocol composition can)
- You're working with
structs/enums, which can't inherit at all - You want to avoid deep, fragile class hierarchies that are hard to change later
Reach for inheritance only when there's a genuine "is-a" relationship and you need to share both implementation and a common type for polymorphic storage — e.g., UIViewController subclasses, where the framework itself dictates the hierarchy.
// Composition: Car is built from independently-testable pieces
struct Engine { func start() { } }
struct Wheels { func roll() { } }
struct Car {
let engine: Engine
let wheels: Wheels
func drive() {
engine.start()
wheels.roll()
}
}
This mirrors the broader Swift philosophy: model "is-a" relationships with protocols and "has-a" relationships with composition, reserving class inheritance for cases the platform requires.