पाठ 7 / 25

Structs and Value Semantics

Model data with structs, properties and methods, and understand value semantics.

The default building block

A struct groups properties and methods into a value type: assigning or passing a struct copies it, so two variables never accidentally share state. Swift's own Int, String, Array and Dictionary are structs. Structs get a memberwise initialiser automatically. Stored properties hold data; computed properties derive values (var total: Double { price * Double(quantity) }); property observers (willSet, didSet) react to changes; and lazy properties are created on first use. Methods that change a struct's properties must be marked mutating, and they can only be called on var instances. Apple's guidance is to prefer structs by default and use classes only when you need reference semantics, identity or inheritance, or when interoperating with Objective-C APIs. Value semantics make code easier to reason about and are especially valuable with concurrency, since copies cannot be raced on.

Value versus reference semantics

Copying a struct creates an independent value; copying a class reference points to the same object.

Left: two separate boxes after a copy arrow. Right: two labels with arrows pointing to one shared box.
Figure 3.1 — Structs copy values; classes share instances.

A struct with computed properties and a mutating method

Copies are independent; mutation is explicit.

struct CartItem {
    let sku: String
    let unitPrice: Double
    var quantity: Int {
        didSet { if quantity < 0 { quantity = 0 } }   // property observer
    }

    var lineTotal: Double { unitPrice * Double(quantity) }   // computed property

    mutating func add(_ count: Int) {
        quantity += count
    }
}

var pen = CartItem(sku: "PEN-BLUE", unitPrice: 49.5, quantity: 2)   // memberwise init
var anotherPen = pen          // independent copy
anotherPen.add(3)
print(pen.quantity)           // 2
print(anotherPen.quantity)    // 5

let fixed = CartItem(sku: "INK", unitPrice: 120, quantity: 1)
// fixed.add(1)               // error: cannot call mutating method on a let constant

Start with a struct

When modelling data, begin with a struct. Switch to a class only when you can name the reason: shared identity, inheritance, deinit cleanup or an API that requires a class.

त्वरित जाँच: Why must some struct methods be marked mutating?

  • Because they modify the struct's own properties, which value types only allow explicitly
  • To make them public
  • To make them asynchronous
  • Because structs cannot have methods
Answer

Because they modify the struct's own properties, which value types only allow explicitly — mutating marks methods that change self, and they require a var instance.