# Structs and Value Semantics — Swift

Source: https://www.skillbyai.com/en/swift/t-structs

> 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.](assets/figures/swift/section-3-map.svg) — Figure 3.1 — Structs copy values; classes share instances.

## A struct with computed properties and a mutating method

Copies are independent; mutation is explicit.

```swift
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.

**Quiz:** Why must some struct methods be marked mutating?

- [x] 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.
