Protocol-Oriented Programming in Swift
Protocol-oriented programming swaps inheritance for composable capabilities via protocol extensions. Use it to share behavior across structs without forcing a superclass. The footgun is protocol bloat: indirection without reuse is bureaucracy.
Why it exists
Swift structs and enums are value types, which means they cannot inherit from a base class or share behavior through subclassing. Early Swift code often shoehorned everything into classes just to reuse code, accepting reference semantics and the risk of shared mutable state. Protocol-oriented programming exists to break that dependency by giving value types a mechanism to share implementations without inheritance, preserving safety and performance while still enabling polymorphism.
The mental model
Stop drawing family trees and start snapping on capabilities. In protocol-oriented programming, a type is defined by what it can do, not who its parent is. You write a protocol to declare an interface, then use an extension to attach a default implementation to that protocol. Any conforming type picks up the behavior automatically, like adding a module to a spaceship rather than being born into a royal bloodline.
How it works
You declare a protocol with requirements such as methods or properties. Then you write an extension on the protocol itself and provide default implementations for those requirements. A struct, enum, or class that conforms to the protocol receives the defaults for free, but can override any of them. Because Swift protocols support associated types and Self requirements, the compiler can resolve these statically in many cases, avoiding the runtime overhead of dynamic dispatch that often comes with class inheritance.
When to use it
Reach for protocol-oriented programming when you need to share code across multiple types that should remain value types, or when you want to model cross-cutting concerns like serialization, equatability, or network request construction. It is also the standard way to write testable code in Swift. Define a protocol for a network client, inject a mock conforming type in tests, and use the real implementation in production without changing your call sites.
When not to use it
Do not reach for a protocol when only one concrete type will ever implement it. A protocol with a single conforming type is usually premature abstraction that adds cognitive overhead and slows compile times. Also avoid protocol-oriented programming when you genuinely need reference identity, shared mutable state, or Objective-C interoperability that relies on dynamic runtime behavior, because structs and static dispatch cannot satisfy those requirements.
One canonical example
Imagine you are building a graphics renderer. You define a Drawable protocol with a draw method, and you write a protocol extension that provides a default implementation using a shared rendering pipeline. A struct Circle, a struct Rectangle, and even a class TextLabel can all conform to Drawable. They each inherit nothing from one another, yet they all gain the default draw logic. You can store them in a homogeneous array of Drawable existentials and call draw on each element, achieving polymorphism while keeping the shapes as lightweight value types wherever possible.
Interview question
In Swift, when should you reach for protocol-oriented programming instead of a class hierarchy?
- a.When you need reference identity and shared mutable state across subclasses
- b.When you rely on Objective-C runtime dynamic dispatch for polymorphism
- c.When multiple value types need to share implementation logic without inheritanceCorrect
- d.When only one concrete type will ever need the behavior, but you want default implementations
Why? this is the answer
Protocol-oriented programming lets structs and enums share behavior via protocol extensions without class inheritance, preserving value semantics. Option D is tempting because protocols do offer default implementations, but applying a protocol to a single type is premature abstraction that creates indirection without actual reuse.
Just read this? Test yourself on what you have been reading.
Put your scrolling time to good use
Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.
We are hiring for this. Open roles that interview on swift — each one lists the topics its interview covers.
See open roles