Inheritance
Essence
Inheritance is the mechanism by which a class receives the properties and methods of a parent class and can extend or override them. It is an "is-a" relationship: a Circle is a Shape. Inheritance gives subtype polymorphism: wherever a Shape is expected you may pass a Circle.
In Swift
- Only classes inherit;
struct,enumandactordo not; they reuse code through protocols andextensions. - Inheritance is single: one superclass, any number of protocols.
overrideis mandatory when overriding,supercalls the parent implementation,finalforbids subclassing (and lets the compiler use static dispatch instead of the vtable).- Initializers: designated/convenience, two-phase initialization,
required initmust be implemented by subclasses.
class Shape {
func area() -> Double { 0 }
func describe() -> String { "area = \(area())" }
}
final class Circle: Shape {
let radius: Double
init(radius: Double) { self.radius = radius }
override func area() -> Double { .pi * radius * radius }
override func describe() -> String { "circle, " + super.describe() }
}
let shapes: [Shape] = [Circle(radius: 1), Shape()]
for s in shapes { print(s.describe()) }
// circle, area = 3.141592653589793
// area = 0.0
Benefits and cost
- Benefit: less duplication and a ready extension point (UIKit is built entirely on
UIView/UIViewController). - Cost: the fragile base class problem: changing the parent breaks subclasses; a subclass depends on the parent's implementation details, so inheritance partly breaks encapsulation.
- Deep hierarchies are hard to read (behaviour is smeared across levels) and to test.
- Design rule: "prefer composition over inheritance"; subclass when you genuinely need to override framework behaviour or there is an honest is-a relationship.