पाठ 13 / 25
Protocols and Extensions
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.
A protocol with a default implementation and synthesised conformances
Conforming types get describe() for free.
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.
त्वरित जाँच: How can a protocol provide behaviour shared by all conforming types?
- 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.