# Protocols and Extensions — Swift

Source: https://www.skillbyai.com/en/swift/p-protocols

> Define protocols, conform types to them and add behaviour with extensions.

## Contracts and retroactive behaviour

A **protocol** defines requirements (methods, properties, initialisers) that conforming types must provide. Structs, enums and classes can all conform to **many** protocols, which is how Swift shares behaviour without inheritance. **Extensions** add methods, computed properties, initialisers and protocol conformances to existing types, even ones you did not write, such as adding a `formattedINR` property to `Double`. **Protocol extensions** provide **default implementations** for requirements, so conforming types get behaviour for free and override only what they need. Swift can **synthesise** common conformances automatically: **`Equatable`**, **`Hashable`** and **`Codable`** for structs whose properties conform, and **`Comparable`** for enums. Organising a type's conformances in separate extensions (`extension Order: Codable {}`) keeps code tidy. Protocols can inherit from other protocols and can be restricted to classes with `AnyObject`, for example for delegates held weakly.

## Protocols as plug shapes

Different types plug into the same protocol; extensions add shared behaviour for all of them.

![Three differently shaped blocks each fitted with the same connector shape plugging into one socket.](assets/figures/swift/section-5-map.svg) — Figure 5.1 — Types conforming to a protocol with a default implementation.

## A protocol with a default implementation and synthesised conformances

Conforming types get describe() for free.

```swift
protocol Shippable {
    var weightGrams: Int { get }
    var isFragile: Bool { get }
}

extension Shippable {
    var shippingFeePaise: Int {                       // default implementation
        let base = weightGrams <= 500 ? 4_900 : 9_900
        return isFragile ? base + 2_500 : base
    }
}

struct Book: Shippable, Hashable, Codable {           // Hashable and Codable synthesised
    let isbn: String
    let title: String
    let weightGrams: Int
    var isFragile: Bool { false }
}

struct VaseOrder: Shippable {
    let weightGrams: Int
    let isFragile = true
}

extension Double {
    var formattedINR: String { formatted(.currency(code: "INR")) }   // extend an existing type
}

let items: [any Shippable] = [Book(isbn: "978-0", title: "Swift", weightGrams: 400), VaseOrder(weightGrams: 900)]
let totalFee = items.reduce(0) { $0 + $1.shippingFeePaise }
print(Double(totalFee / 100).formattedINR)
```

## Conformance in extensions

Writing `extension Order: Codable { ... }` separately from the main type groups each protocol's requirements together, making large types far easier to navigate.

**Quiz:** How can a protocol provide behaviour shared by all conforming types?

- [x] Through a protocol extension with default implementations
- [ ] Through inheritance only
- [ ] By making the protocol a class
- [ ] It cannot

*Answer:* Through a protocol extension with default implementations. Protocol extensions supply default implementations that conforming types inherit.
