Protocols
A Swift protocol is a contract — required methods, properties, associated types. Conform with extension Type: Protocol. Protocol extensions add default implementations. Generic constraints unlock zero-cost abstractions.
Define, conform, extension, associated
EXAMPLE
// 1) Define a protocol
protocol Describable {
var description: String { get }
}
// 2) Conform — by extension
struct User { let name: String }
extension User: Describable {
var description: String { "User: \\(name)" }
}
// 3) Protocol with default implementation
protocol Greetable {
var name: String { get }
func greet() -> String
}
extension Greetable {
func greet() -> String { "Hi, I'm \\(name)" }
}
struct Robot: Greetable { let name: String }
print(Robot(name: "R2").greet()) // uses the default
// 4) Composition — conform to multiple
protocol Identifiable2 {
associatedtype ID: Hashable
var id: ID { get }
}
protocol Timestamped {
var createdAt: Date { get }
}
struct Post: Identifiable2, Timestamped {
let id: UUID
let createdAt: Date
let title: String
}
// 5) Generic constraints
func printAll<T: Describable>(_ items: [T]) {
items.forEach { print($0.description) }
}
// 6) Existential — `any Protocol` (boxed)
func printAny(_ items: [any Describable]) {
items.forEach { print($0.description) }
}
// Existential = heterogenous array; generic = monomorphised at compile-time.
// 7) Constrained existentials (Swift 5.7+)
func print(_ items: any Collection<String>) { /* … */ }
// 8) Associated types — generic protocols
protocol Storage {
associatedtype Item
func add(_ item: Item)
func all() -> [Item]
}
struct UserStore: Storage {
typealias Item = User
var users: [User] = []
mutating func add(_ item: User) { users.append(item) }
func all() -> [User] { users }
}
// 9) Protocol witness — manual dispatch (testable mocks)
struct AnalyticsClient {
var track: (String, [String: Any]) -> Void
}
extension AnalyticsClient {
static var live: Self {
.init { event, props in /* send to Mixpanel */ }
}
static var mock: Self {
.init { event, props in print("mock: \\(event) \\(props)") }
}
}
// 10) Equatable, Hashable, Codable — auto-conformance when all fields conform
struct Money: Equatable, Hashable, Codable {
let amount: Decimal
let currency: String
}
// 11) CustomStringConvertible — printable
struct Tag: CustomStringConvertible {
let value: String
var description: String { "#\\(value)" }
}
print(Tag(value: "swift")) // "#swift"
// 12) Where clauses — constrain associated types
func sum<T: Sequence>(_ s: T) -> Int where T.Element == Int {
s.reduce(0, +)
}
extension Collection where Element == String {
func longest() -> String? { self.max(by: { $0.count < $1.count }) }
}
// 13) Result-builder + protocol — SwiftUI-style declarative views
protocol View2 { var body: String { get } }
struct Text2: View2 { let s: String; var body: String { s } }
struct Row2: View2 { let items: [String]; var body: String { items.joined(separator: " ") } }
// 14) Sealed-ish hierarchy with protocols + final classes / structs
protocol Animal { func sound() -> String }
final class Dog: Animal { func sound() -> String { "woof" } }
final class Cat: Animal { func sound() -> String { "meow" } }
// 15) Common pitfalls
// • Forgetting `mutating` on a method in a value type that conforms to a protocol
// • Self requirements (Self: Equatable) → can't be used as `any Equatable` (until newer Swift)
// • Overriding default implementations — order: extension > type-specific > default
// • Existential overhead — `any P` boxes values; prefer generic for hot paths
Why it matters
Protocol + extension is Swift’s favourite composition tool. Default implementations replace inheritance; generic constraints monomorphise at compile time — abstraction without runtime cost.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
protocol Greet {
func hello() -> String
}
struct User: Greet {
let name: String
func hello() -> String { "hi, \(name)" }
}
Try it Yourself »
Exercise
Adopt a protocol.
struct User:
{ func hello() -> String { "hi" } }
Five letters PascalCase.
Discussion
Loading…