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.