Polymorphism
Essence
Polymorphism is the ability to work with different types through one interface: one call, different implementations. "One interface, many implementations." Swift has four practically important kinds.
Kinds in Swift
// 1. Subtype polymorphism: class hierarchy, vtable dispatch
class Animal { func sound() -> String { "..." } }
class Dog: Animal { override func sound() -> String { "Woof" } }
// 2. Protocol polymorphism: witness table (existential `any`)
protocol Drawable { func draw() -> String }
struct Square: Drawable { func draw() -> String { "□" } }
struct Dot: Drawable { func draw() -> String { "•" } }
let items: [any Drawable] = [Square(), Dot()]
print(items.map { $0.draw() }.joined()) // □•
// 3. Parametric polymorphism: generics, static dispatch + specialization
func largest<T: Comparable>(_ values: [T]) -> T? { values.max() }
print(largest([3, 9, 2]) ?? 0) // 9
print(largest(["b", "a"]) ?? "") // b
// 4. Ad hoc polymorphism: overloading
func describe(_ x: Int) -> String { "int \(x)" }
func describe(_ x: String) -> String { "string \(x)" }
print(describe(1), describe("a")) // int 1 string a
- Subtype: a subclass stands in for its superclass; the method is chosen at runtime through the vtable.
- Protocol-based: any type adopting the protocol fits
any P; the call goes through a protocol witness table. This is the main kind of polymorphism in Swift and works forstruct/enumtoo. - Parametric: generics; the code is written once for any
Tand the compiler specializes it for the concrete type (static dispatch, no boxing). - Ad hoc: function and operator overloading; the compiler picks by argument types.
What the interviewer looks for
- Understanding the cost: dynamic dispatch (
any P, non-final classes) is cheaper than it sounds but blocks inlining;some Pand generics give static dispatch. - Methods in a protocol
extensionthat are not requirements of the protocol are dispatched statically: the classic trap where a call throughany Ppicks the extension implementation, not the type's own. final/privatelet the compiler drop vtable calls (devirtualization).