Are immutable structs like classes?

(Vinicius Vendramini) #1

I've been talking about this for a while with a few friends, and it seems quite intriguing. Also, it would be very useful to me if it was true.

People often demonstrate the differences between passing a variable by value or by reference by mutating the variable and showing how it changes (or doesn't). For instance:

struct S {
	var x = 0

class C {
	var x = 0

var s1 = S()
var s2 = s1
s2.x = 1

var c1 = C()
var c2 = c1
c2.x = 1

print(s1.x) // 0
print(s2.x) // 1

print(c1.x) // 1
print(c2.x) // 1

In this case, since structs are passed by value and classes are passed by reference, their behaviors are different.

Say, however, that a struct was created that was never allowed to mutate. I think this could be done by using only lets and non-mutating methods, but we could also rely on the user never mutating it intentionally.

In this case, is there any way to observe a difference between the behavior of a struct and a class (with the same properties and methods) other than performance differences and such?

(Joe Groff) #2

It is true that you can use an immutable class and struct both as value types, since the only way to model a change in either is to replace with a completely different value. Classes still have some observable differences:

  • Classes have identity, whereas struct values do not. Even if two immutable class instances have the same stored properties, you can distinguish them by testing for ===, whereas there is no way to do so for struct values. (There are various ways to peek at the identity of struct variables, with lots of caveats, but not the values themselves.)
  • Classes support inheritance, so the dynamic type of an immutable class instance may differ from its formal type known at compile-time, whereas the type is always fixed for a struct.

(Vinicius Vendramini) #3

Yes! I's thought about inheritance, but identity is also important. Thanks a lot!

(Vinicius Vendramini) #4

Oh, am I right to assume that, barring similar differences (probably more significant), enums can also work in a similar way, as "the only way to model a change in either is to replace with a completely different value"?