{"id":"l-sw-2-3","courseId":"swift-essentials","lang":"en","kind":"lesson","summary":"Define protocols as contracts, adopt standard ones like Identifiable and Hashable, add default behaviour with protocol extensions, and extend types you don’t own.","html":"<p>Pocket Budget is about to grow a second kind of cost. Next to one-off expenses there are subscriptions, billed monthly or yearly. The summary screen shouldn’t care which is which: it needs a title and a monthly cost from each. Inheritance would force both into a class hierarchy. Swift’s answer is a <strong>protocol</strong>: a list of requirements any type can promise to meet, whether it’s a struct, a class or an enum.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">Writing a protocol</h2>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">BudgetItem.swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Foundation</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">protocol</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> BudgetItem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> title: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">get</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> monthlyCost: Decimal { </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">get</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p><code dir=\"ltr\">{ get }</code> means “readable”. A conforming type can satisfy it with a stored property or a computed one. Here are two conforming types, building on the <code dir=\"ltr\">Category</code> enum from the previous lesson:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">struct</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Expense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">Identifiable</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">Hashable</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">BudgetItem </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> id </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> UUID</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">()</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> title: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount: Decimal</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> category: Category</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> date: Date</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> monthlyCost: Decimal { amount }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">struct</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Subscription</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">BudgetItem </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> title: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> price: Decimal</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> billedYearly: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">Bool</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> monthlyCost: Decimal {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">        billedYearly </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> price </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 12</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> :</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> price</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>Leave out <code dir=\"ltr\">monthlyCost</code> and the compiler stops you with “type ‘Subscription’ does not conform to protocol ‘BudgetItem’”, and Xcode offers to add stubs for whatever is missing.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">Standard protocols you’ll use every day</h2>\n<p><code dir=\"ltr\">Expense</code> also adopts two protocols from the standard library. <strong>Identifiable</strong> requires an <code dir=\"ltr\">id</code> property, and SwiftUI’s <code dir=\"ltr\">List</code> and <code dir=\"ltr\">ForEach</code> use it to tell rows apart, so you’ll see it on nearly every model in this course. <strong>Hashable</strong> lets expenses go into a <code dir=\"ltr\">Set</code> or be dictionary keys, and it includes <strong>Equatable</strong>, which gives you <code dir=\"ltr\">==</code>.</p>\n<p>You didn’t write <code dir=\"ltr\">==</code> or a hash function. For structs and enums, Swift <strong>synthesizes</strong> <code dir=\"ltr\">Equatable</code> and <code dir=\"ltr\">Hashable</code> when every stored property already conforms, and <code dir=\"ltr\">UUID</code>, <code dir=\"ltr\">String</code>, <code dir=\"ltr\">Decimal</code>, <code dir=\"ltr\">Date</code> and <code dir=\"ltr\">Category</code> all do. Because <code dir=\"ltr\">id</code> is part of that comparison, two expenses with identical titles and amounts are still different expenses, which is what the user means.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">Common mistake</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>A protocol with one conforming type</span></p>\n<p>Beginners often write <code dir=\"ltr\">protocol ExpenseProtocol</code> next to <code dir=\"ltr\">struct Expense</code> “for flexibility”. A protocol with a single implementation adds a layer to read and buys nothing. Introduce one when a second type actually needs to fit the same slot, as <code dir=\"ltr\">Subscription</code> does here, or when tests need a fake.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">Default behaviour with protocol extensions</h2>\n<p>Every budget item needs a formatted price. Instead of writing it twice, extend the protocol:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">extension</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> BudgetItem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    func</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> formattedCost</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">currencyCode</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> =</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"USD\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">        monthlyCost.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">formatted</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">currency</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">code</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: currencyCode))</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> coffee </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Expense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">title</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Coffee\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">amount</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">4.5</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">category</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: .food, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">date</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: .now)</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> music </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> Subscription</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">title</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Music\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">price</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">120</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">billedYearly</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">true</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">coffee.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">formattedCost</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">()                     </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// \"$4.50\"</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">music.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">formattedCost</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">currencyCode</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"EUR\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)   </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// \"€10.00\"</span></span></code></pre></div>\n<p>Every type that conforms to <code dir=\"ltr\">BudgetItem</code>, now or in the future, gets <code dir=\"ltr\">formattedCost</code> for free. This is the core of what people mean by protocol-oriented Swift: small protocols, with shared behaviour in extensions, adopted by value types.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 680 230\" role=\"img\" aria-labelledby=\"l-sw-2-3-t1\"><defs><marker id=\"arrow-l-sw-2-3-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-sw-2-3-t1\">Expense and Subscription both conform to the BudgetItem protocol, which requires title and monthlyCost. A protocol extension adds formattedCost to every conforming type.</title>\n  <rect class=\"d-box-primary\" x=\"230\" y=\"20\" width=\"220\" height=\"70\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"340\" y=\"48\" text-anchor=\"middle\">protocol BudgetItem</text>\n  <text class=\"d-label-muted\" x=\"340\" y=\"72\" text-anchor=\"middle\">title, monthlyCost</text>\n  <rect class=\"d-box-accent\" x=\"490\" y=\"30\" width=\"180\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"580\" y=\"60\" text-anchor=\"middle\">formattedCost()</text>\n  <path class=\"d-line d-dashed\" d=\"M450 55 L490 55\"/>\n  <text class=\"d-label-muted\" x=\"580\" y=\"102\" text-anchor=\"middle\">from the extension</text>\n  <rect class=\"d-box-success\" x=\"80\" y=\"150\" width=\"200\" height=\"56\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"180\" y=\"183\" text-anchor=\"middle\">struct Expense</text>\n  <rect class=\"d-box-success\" x=\"400\" y=\"150\" width=\"220\" height=\"56\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"510\" y=\"183\" text-anchor=\"middle\">struct Subscription</text>\n  <path class=\"d-arrow\" d=\"M180 150 L300 92\" marker-end=\"url(#arrow-l-sw-2-3-1)\"/>\n  <path class=\"d-arrow\" d=\"M510 150 L380 92\" marker-end=\"url(#arrow-l-sw-2-3-1)\"/>\n  <text class=\"d-label-muted\" x=\"340\" y=\"135\" text-anchor=\"middle\">conforms</text>\n</svg><figcaption>Two types, one protocol, shared behaviour</figcaption></figure>\n<h2 id=\"sec-4\" tabindex=\"-1\">some and any</h2>\n<p>Two keywords describe “a value of some type that conforms”:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items: [</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">any</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> BudgetItem] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> [coffee, music]</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">let</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> monthly </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">reduce</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> +</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> $1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.monthlyCost }    </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// 14.5</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">func</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> cheapest</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">_</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> list: [</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">some</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> BudgetItem]) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">-></span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> String</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    list.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">min</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">$0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.monthlyCost </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">&#x3C;</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> $1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.monthlyCost }</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">?</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">.title</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p><code dir=\"ltr\">any BudgetItem</code> is a box that can hold a different conforming type in each slot, which is what a mixed list needs. <code dir=\"ltr\">some BudgetItem</code> means “one specific conforming type, decided by the caller”: <code dir=\"ltr\">cheapest</code> works with <code dir=\"ltr\">[Expense]</code> or <code dir=\"ltr\">[Subscription]</code>, but not with a mix. Prefer <code dir=\"ltr\">some</code> when it fits, because the compiler knows the exact type and can optimize. SwiftUI’s <code dir=\"ltr\">var body: some View</code> uses the same keyword in return position, where the roles flip: the view’s implementation picks the one concrete type, and callers only know it’s a <code dir=\"ltr\">View</code>.</p>\n<h2 id=\"sec-5\" tabindex=\"-1\">Extending types you don’t own</h2>\n<p>Extensions aren’t limited to protocols. You can add computed properties, methods and conformances to any type, including Apple’s:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">extension</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Decimal</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> asCurrency: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">formatted</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">currency</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">code</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"USD\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)) }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">extension</span><span style=\"color:#953800;--shiki-dark:#FFA657\"> Expense</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">CustomStringConvertible </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    var</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> description: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">String</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> { </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">\\(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">title</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> (</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">\\(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">category.</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">rawValue</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">): </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">\\(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">formattedCost</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">()</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">)</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> }</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(coffee)   </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">// Coffee (food): $4.50</span></span></code></pre></div>\n<p>Many Swift teams also use extensions to organise a file: the type’s stored properties at the top, then one extension per conformance. One limit applies everywhere: an extension can’t add <strong>stored</strong> properties, only computed ones. Also, when an extension method on a struct changes a property, it still needs <code dir=\"ltr\">mutating</code>, exactly like a method in the original declaration.</p>\n<h2 id=\"sec-6\" tabindex=\"-1\">Where you’ll meet protocols next</h2>\n<p>Protocols are how Apple’s frameworks talk to your code. In SwiftUI, every screen you build is a struct that conforms to the <code dir=\"ltr\">View</code> protocol, whose single requirement is a <code dir=\"ltr\">body</code> property. <code dir=\"ltr\">List</code> asks for <code dir=\"ltr\">Identifiable</code> elements so it can track rows. Networking code asks for <code dir=\"ltr\">Codable</code> so JSON can become your types. Swift 6 concurrency asks for <code dir=\"ltr\">Sendable</code> before a value may cross between threads. Each time, the pattern is the one from this lesson: the framework states a contract, your type promises to meet it, and the compiler checks the promise.</p>\n<p>You now have the full modelling toolkit: structs, classes, enums and protocols. The last piece before SwiftUI is what happens when an operation fails, such as an expense that would blow the budget, and how Swift’s error handling makes failure part of a function’s type.</p>\n","toc":[{"id":"sec-1","text":"Writing a protocol","level":2},{"id":"sec-2","text":"Standard protocols you’ll use every day","level":2},{"id":"sec-3","text":"Default behaviour with protocol extensions","level":2},{"id":"sec-4","text":"some and any","level":2},{"id":"sec-5","text":"Extending types you don’t own","level":2},{"id":"sec-6","text":"Where you’ll meet protocols next","level":2}],"takeaways":["A protocol lists requirements; any struct, class or enum that implements them can be used wherever the protocol is expected.","For structs and enums, Swift synthesizes <code dir=\"ltr\">Equatable</code> and <code dir=\"ltr\">Hashable</code> automatically when every stored property already conforms.","A protocol extension gives every conforming type a default implementation for free.","Extensions add methods, computed properties and conformances to any type, including ones from Apple, but never new stored properties.","<code dir=\"ltr\">some Protocol</code> stands for one specific conforming type (for a parameter, the caller picks it); <code dir=\"ltr\">any Protocol</code> is a box that can hold a different conforming type each time."],"further":[{"title":"Protocols","url":"https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols/"},{"title":"Extensions","url":"https://docs.swift.org/swift-book/documentation/the-swift-programming-language/extensions/"},{"title":"Identifiable","url":"https://developer.apple.com/documentation/swift/identifiable"}],"quiz":[{"q":"<p><code dir=\"ltr\">struct Expense: Hashable</code> has properties of type <code dir=\"ltr\">UUID</code>, <code dir=\"ltr\">String</code> and <code dir=\"ltr\">Decimal</code>. What do you have to write to make it hashable?</p>","options":[{"text":"Nothing more; Swift synthesizes <code dir=\"ltr\">==</code> and <code dir=\"ltr\">hash(into:)</code> because every property is already hashable.","why":"Correct. Synthesis covers structs and enums whose stored properties all conform."},{"text":"A <code dir=\"ltr\">hash(into:)</code> method that combines each property by hand.","why":"You can, but only when you want different behaviour from the synthesized version."},{"text":"An <code dir=\"ltr\">extension Expense: Equatable</code> with a custom <code dir=\"ltr\">==</code>.","why":"<code dir=\"ltr\">Hashable</code> inherits from <code dir=\"ltr\">Equatable</code>, and both are synthesized together."}],"answer":0},{"q":"<p>Why can’t you add <code dir=\"ltr\">var note: String = &quot;&quot;</code> to <code dir=\"ltr\">Decimal</code> in an extension?</p>","options":[{"text":"Extensions can only add methods, not properties of any kind.","why":"Extensions can add computed properties, like <code dir=\"ltr\">var asCurrency: String { … }</code>."},{"text":"<code dir=\"ltr\">Decimal</code> is a struct, and structs can’t be extended.","why":"Any type can be extended, including Apple’s structs."},{"text":"Extensions can’t add stored properties, because that would change the type’s memory layout.","why":"Correct. Add a computed property, or wrap the value in your own type."}],"answer":2},{"q":"<p>You need one array holding both <code dir=\"ltr\">Expense</code> and <code dir=\"ltr\">Subscription</code> values, which both conform to <code dir=\"ltr\">BudgetItem</code>. Which type do you declare?</p>","options":[{"text":"<code dir=\"ltr\">[some BudgetItem]</code>","why":"<code dir=\"ltr\">some</code> means one concrete type for the whole array; it can’t mix expenses with subscriptions."},{"text":"<code dir=\"ltr\">[any BudgetItem]</code>","why":"Correct. Each element is an existential box that can hold any conforming type."},{"text":"<code dir=\"ltr\">[BudgetItem.Type]</code>","why":"That’s an array of types (metatypes), not of values."}],"answer":1},{"q":"<p>A protocol extension defines <code dir=\"ltr\">formattedCost()</code>. <code dir=\"ltr\">Subscription</code> conforms but doesn’t implement it. What happens when you call <code dir=\"ltr\">music.formattedCost()</code>?</p>","options":[{"text":"A compile error, because <code dir=\"ltr\">Subscription</code> is missing a requirement.","why":"A method supplied by a protocol extension is satisfied for every conforming type automatically."},{"text":"A runtime crash, because the method has no body in <code dir=\"ltr\">Subscription</code>.","why":"The body lives in the extension, so there’s always something to run."},{"text":"The default implementation from the extension runs.","why":"Correct. That’s the purpose of a protocol extension: shared behaviour written once."}],"answer":2}],"exercise":{"kind":"spot-bug","language":"swift","code":"import Foundation\n\nstruct Budget {\n    var limit: Decimal\n    var spent: Decimal = 0\n}\n\nextension Budget: CustomStringConvertible {\n    var remaining: Decimal { limit - spent }\n    var description: String { \"\\(spent) of \\(limit) spent\" }\n\n    func record(_ amount: Decimal) { spent += amount }\n}\n\nvar food = Budget(limit: 300)\nfood.record(42)\nprint(food)","bugLines":[12],"title":"The extension that won't compile","prompt":"<p>A teammate moved <code dir=\"ltr\">Budget</code>’s behaviour into an extension, and now the project doesn’t build. Select the line the compiler rejects.</p>\n","hints":["<code dir=\"ltr\">Budget</code> is a struct. Which line in the extension changes one of its stored properties?","Computed properties only read <code dir=\"ltr\">limit</code> and <code dir=\"ltr\">spent</code>. Look for an assignment.","Methods on structs that change <code dir=\"ltr\">self</code> need a keyword in front of <code dir=\"ltr\">func</code>."],"explanation":"<p>Line 12 changes <code dir=\"ltr\">spent</code> from a plain method, and struct methods can’t modify <code dir=\"ltr\">self</code> unless they’re marked <code dir=\"ltr\">mutating</code>. The compiler reports “left side of mutating operator isn’t mutable: ‘self’ is immutable”. Moving code into an extension doesn’t change the rules:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"swift\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Swift</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">mutating</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> func</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> record</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\">_</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount: Decimal) { spent </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> amount }</span></span></code></pre></div>\n<p>The call site already uses <code dir=\"ltr\">var food</code>, so it compiles once the method is <code dir=\"ltr\">mutating</code>. With <code dir=\"ltr\">let food</code> it would fail again, for the reason you saw in the structs lesson.</p>\n","checkLabels":{}},"words":703,"readMinutes":3}