Lesson 73Protocols
Protocol Inheritance
Protocol Inheritance
Protocols can inherit from one or more other protocols, adding new requirements on top. This creates powerful, composable interfaces!
Inheritance Syntax
protocol Child: Parent1, Parent2 {
// Additional requirements
}
// Additional requirements
}
Key Concepts
Multiple Inheritance
Protocols can inherit from many protocols
protocol C: A, B { }Protocol Composition
Combine protocols with &
func f(_ p: A & B)Typealias
Name composed protocols
typealias AB = A & BConformance Check
Check with is/as
if obj is ProtocolProtocol Composition
Use & to require multiple protocols:
func process(_ item: Codable & Identifiable)The parameter must conform to BOTH protocols!
Hierarchy Example
Vehicle
├── LandVehicle
├── WaterVehicle
└── AmphibiousVehicle (both)
main.swift
// PROTOCOL INHERITANCE
// Protocols can inherit from other protocols
// SINGLE INHERITANCE
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
// Inheriting from single protocol
protocol Identifiable: Named {
var id: String { get }
}
// MULTIPLE INHERITANCE
// Protocols can inherit from multiple protocols
protocol Person: Named, Aged {
var occupation: String { get }
}
struct Employee: Person {
var name: String
var age: Int
var occupation: String
}
let employee = Employee(name: "Alice", age: 30, occupation: "Developer")
print("\(employee.name), \(employee.age), \(employee.occupation)")
// PROTOCOL COMPOSITION
// Combine protocols temporarily with &
func greet(person: Named & Aged) {
print("Hello \(person.name), you are \(person.age) years old")
}
greet(person: employee) // Works because Employee conforms to both
// USING TYPEALIAS FOR COMPOSITION
typealias PersonInfo = Named & Aged
func printInfo(_ info: PersonInfo) {
print("\(info.name) is \(info.age)")
}
// BUILDING PROTOCOL HIERARCHIES
protocol Drawable {
func draw()
}
protocol Colorable {
var color: String { get }
}
protocol Shape: Drawable, Colorable {
var area: Double { get }
}
struct Circle: Shape {
var radius: Double
var color: String
var area: Double {
return Double.pi * radius * radius
}
func draw() {
print("Drawing a \(color) circle with area \(area)")
}
}
// SPECIALIZED PROTOCOLS
protocol Vehicle {
var speed: Int { get }
func move()
}
protocol LandVehicle: Vehicle {
var wheels: Int { get }
}
protocol WaterVehicle: Vehicle {
var draft: Double { get } // How deep in water
}
protocol AmphibiousVehicle: LandVehicle, WaterVehicle {
func switchMode()
}
struct Hovercraft: AmphibiousVehicle {
var speed: Int
var wheels: Int = 0
var draft: Double
func move() {
print("Hovering at \(speed) mph")
}
func switchMode() {
print("Switching between land and water mode")
}
}
// CLASS-ONLY PROTOCOL INHERITANCE
protocol ViewControllerDelegate: AnyObject {
func didLoad()
}
protocol TableViewDelegate: ViewControllerDelegate {
func didSelectRow(at index: Int)
}
// Implementation must be a class
class MyTableDelegate: TableViewDelegate {
func didLoad() {
print("View loaded")
}
func didSelectRow(at index: Int) {
print("Selected row \(index)")
}
}
// CHECKING PROTOCOL CONFORMANCE
let shape: Any = Circle(radius: 5, color: "red")
if let drawable = shape as? Drawable {
drawable.draw()
}
if shape is Shape {
print("It's a shape!")
}Try It Yourself!
Create a protocol hierarchy for a media app: Playable → AudioPlayable and VideoPlayable → StreamableMedia (combines both)!