Recipes for value semantics
To summarize, here is the recipe for determining if a type has value semantics or how to define your own such type:
For a reference type (a class):
- The type must be immutable, which requires that all its properties be constant. All its properties must be of types that have value semantics.
For a value type (a struct or enum):
- A primitive value type like Int always has value semantics.
- If you define a struct type with properties, that type will have value semantics if all of its properties have value semantics.
- Similarly, if you define an enum type with associated values, that type will have value semantics if all its associated values have value semantics.
For copy-on-write value types (a struct or enum):
- Choose the “value-semantics access level”, that is, the access level which will expose an interface that preserves value semantics.
- Make note of all mutable reference-type properties, as these are the ones which
spoil automatic value semantics. Set their access level below the value- semantics level.
- Define all the setters and mutating functions at and above the value-semantics access level so that they never actually modify a shared instance of those reference-type properties, but instead assign a copy of the instance to the reference-type property.