Could someone please explain this line of text from chapter 18?

I cannot understand how is this advice any better or how does it actually help:

Page 246 reads: If you find yourself needing a reference type property in your struct, then it is best to use an immutable instance.

Is that referring to an immutable instance of the struct or an immutable instance of the reference type inside the struct? Wouldn’t an immutable instance of the struct still make it possible to change properties inside the reference type? and it if were referring to an immutable instance of the reference type inside the struct, wouldn’t that still allow for changes to properties inside the reference type?

The examples in the chapter go something like this:

class Employee {
    var id: Int = 0
}

struct Company {
    var boss: Employee
}

let anika = Employee()
anika.id = 16

let acme = Company(boss: anika) 
acme.boss.id // this prints 16
let widgetCo = acme
anika.id = 15
widgetCo.boss.id //this prints 15

So from my understanding of the author’s suggestion above, I should make the boss reference type property a constant? but wouldn’t that still allow me to freely change the id property in boss? or should I make the struct instance of Company a constant (which in fact already is) and how would that prevent changes to properties in the boss reference type property itself?

Any help or clarification in this matter would be highly appreciated. Thank you!

Yes, but you should add an initializer to the Employee class and make its id property constant.

class Employee {
   let id: Int
   init (id:Int) {
      self.id = id
   }
}

struct Company {
    let boss: Employee
}

let anika  = Employee (id:16)
let monika = Employee (id:anika.id + 1)

let acme = Company (boss:anika)
acme.boss = monika // error
acme.boss.id = 1   // error

This doesn’t completely answer your question, but it is worth digging around in swift.org to see if they have anything useful to say about this.

Yes it does. Changing the boss property inside Company to be immutable means you can’t change a company’s boss to be a different employee but you can still change the boss’s employee id. And I don’t see a way to make an Employee who’s id is immutable without making every Employee’s id immutable as ibex10 suggests. So I don’t know what the book is trying to suggest here.

In this particular case I agree with making employee ids immutable but that doesn’t entirely solve the problem since a person working for two companies would have different ids at both companies. My solution in this case would include writing an init function for making a Company from another Company that would handle the boss reference by copying the employee and assigning a new id for the new company (a variation on the “deep copy” that they talk about on page 250). Which is generally the method I’ve seen suggested for handling this type of reference problem in other languages - write a custom copy function that handles the references if there’s an issue with them.

However, that doesn’t fix the assignment operator which would still make a straight-up copy of the struct; apparently you can’t overload the assignment operator in Swift. And in a more general sense, making all your class properties immutable to avoid reference issues isn’t really viable even if it is appropriate in some cases. So I don’t really have a good comprehensive solution to offer here.

Is the immutable object concept missing in Swift?

class Key {
   var value = 0
}

// mutable variable, mutable object
var key_mm = Key ()

// mutable variable, immutable object
var key_mi = const Key ()

// immutable variable, mutable object
let key_im = Key ()

// immutable variable, immutable object
let key_ii = const Key ()

// permitted to modify Key
func print (key: Key)

// not permitted to modify Key
func print (key: const Key)

It seems to be, yes. There is no const keyword, only let. You might be able to use custom initializers, private attributes, and non-mutating functions to create a class which cannot be modified after creation.

But an reference to const still wouldn’t solve the problem at the top of the thread where you have another reference to the object that doesn’t define it as const. Take this C code for instance:

int a = 10;
const int *a_ptr = &a;   // mutable pointer to const int
a = 11;
printf("%i", *a_ptr);    // prints 11
*a_ptr = 12;             // error - "Read-only variable is not assignable"

Even though a_ptr points to a const int, the integer it points to isn’t immutable - it just can’t be modified using a_ptr. The same thing would happen if Company was able to define boss as a reference to a const Employee - the Employee object referenced by boss could still be modified by a different reference if one was available.

A reference to a const object doesn’t make any guarantees about the referenced object, it just limits how the reference can be used. Off the top of my head I don’t know if any language lets you specify that a reference can only point to an immutable object other than by making the object’s class be immutable.