Structs and classes

You saved an independent copy of an array in chapter 4. A struct gives a type you define yourself value behavior too. Here is a bookmark with a title and a page number:

struct Bookmark {
    var page: Int
    let title: String

    func label() -> String {
        return "\(title): \(page)"
    }
}

let original = Bookmark(page: 12, title: "Atlas")
var next = original
next.page = 18
print(original.label())
print(next.label())
Atlas: 12
Atlas: 18

The names inside Bookmark are stored properties. var page can change; let title cannot. Hirundo supplies a memberwise initializer for this struct, so Bookmark(page: 12, title: "Atlas") fills in both properties by name. The method label() reads them and returns a string.

next starts with a copy of original. Changing next.page leaves original.page at 12. We call this value semantics: assigning a struct copies its outer value. The two bindings can take different paths from there. next is a var because changing its property changes that bound struct value; original is a let and stays as it was.

One instance, two names

A class behaves differently when you assign one binding to another: both refer to the same instance. This counter has an explicit init, rather than a memberwise initializer supplied for it:

class Counter {
    var count: Int

    init(count: Int) {
        self.count = count
    }

    func advance() {
        count = count + 1
    }
}

let first = Counter(count: 2)
let other = first
other.advance()
print("First: \(first.count)")
print("Other: \(other.count)")
First: 3
Other: 3

self.count on the left is the stored property. The unadorned count on the right is the initializer’s input. The advance() method changes the instance’s var count property.

first and other are both let bindings, but they refer to the same counter. Calling other.advance() changes what first.count reads as well. That is reference semantics. let keeps each binding from being given a different reference; it does not freeze the instance it refers to.

A struct can hold a class reference too. Copying that struct copies its outer value, not the class instance it refers to. Our bookmark holds only an Int and a String, so its two copies can change independently in the way we just saw. We will come back to contained references later.