This.
If a struct
has a memberwise initializer that
- has the same access control of the properties
- doesn't enforce particular invariants
then the properties should always be declared as var
, and that's because if they weren't, I would still be able to reassign an instance of that struct
to a variable by initializing a new one with all the same values of the properties but one.
For example, this piece of code
struct Person {
var name: String
var age: Int
}
var p = Person(name: "Foo", age: 42)
p.age += 1
is (semantically) identical to this
struct Person {
let name: String
let age: Int
}
var p = Person(name: "Foo", age: 42)
p = Person(name: p.name, age: p.age + 1)
the second example makes no sense, and doesn't take advantage of Swift value semantics.
The key difference from a mutable class is the following:
struct PersonStruct {
var name: String
var age: Int
}
let ps = Person(name: "Foo", age: 42) // assigned to a let constant
ps.age += 1 // this is not allowed and doesn't compile
class PersonClass {
var name: String
var age: Int
// it needs an explicit init
}
let pc = Person(name: "Foo", age: 42) // assigned to a let constant
pc.age += 1 // this works and compiles just fine
To me, thinking that "mutable properties" means "class" shows a fundamental misunderstanding of Swift value semantics.