Swift Tutorial · Collections and Types · Lesson 16 of 30

Swift Protocols

Define shared behaviour with protocols, give it default implementations in extensions, and use some and any.

Create a free account to save this page, take notes and track your progress. Sign in

Protocols and extensions

A protocol lists requirements; structs, classes and enums conform to it. A protocol extension can provide default implementations, so conforming types get behaviour for free. Swift is often called a protocol-oriented language.

Protocols with default implementations
import Foundation

protocol Shape {
    var name: String { get }
    func area() -> Double
}

extension Shape {
    func describe() -> String { "\(name) with area \((area() * 10).rounded() / 10)" }   // default implementation
}

struct Square: Shape {
    let side: Double
    var name: String { "square" }
    func area() -> Double { side * side }
}

struct Circle: Shape {
    let radius: Double
    var name: String { "circle" }
    func area() -> Double { Double.pi * radius * radius }
}

let shapes: [any Shape] = [Square(side: 3), Circle(radius: 1)]
for shape in shapes { print(shape.describe()) }

Output

square with area 9.0
circle with area 3.1

Run this on your computer — see “Get Started” for setup.

Standard protocols, some and any

Conform to Equatable, Hashable, Comparable or CustomStringConvertible to plug into the standard library; the compiler synthesises == and hashing for structs. some Shape means "one specific type that conforms" (fast, checked at compile time); any Shape is a box that can hold different conforming types.

Comparable, CustomStringConvertible and some
struct Version: Comparable, CustomStringConvertible {
    let major: Int
    let minor: Int
    static func < (a: Version, b: Version) -> Bool { (a.major, a.minor) < (b.major, b.minor) }
    var description: String { "\(major).\(minor)" }
}

func newest(_ versions: [Version]) -> some CustomStringConvertible {
    versions.max()!
}

let versions = [Version(major: 6, minor: 2), Version(major: 6, minor: 4), Version(major: 5, minor: 10)]
print(versions.sorted())
print(Version(major: 6, minor: 4) == Version(major: 6, minor: 4))   // == is synthesised
print(newest(versions))

Output

[5.10, 6.2, 6.4]
true
6.4

Run this on your computer — see “Get Started” for setup.

Test yourself

What does a protocol extension let you do?

  1. Add stored properties
  2. Provide default implementations for every conforming type
  3. Make a protocol a class
  4. Subclass a struct
Show answer

Answer: Provide default implementations for every conforming type

Was this page helpful?