Value versus reference types

In Swift, there are two kinds of types in terms of memory allocation: value and reference.

Value type instances keep a copy of their data. Each type has its own data and is not referenced by another variable. Structures, enums, and tuples are value types; therefore, they do not share data between their instances. Assignments copy the data of an instance to the other and there is no reference counting involved. The following example presents a struct with copying:

struct OurStruct { 
var data: Int = 3
}

var valueA = OurStruct()
var valueB = valueA // valueA is copied to valueB
valueA.data = 5 // Changes valueA, not valueB
print("(valueA.data), (valueB.data)") // prints "5, 3"

As seen from the preceding example, changing valueA.data does not change valueB.data.

In Swift, arrays, dictionaries, strings, and sets are all value types.

On the other hand, reference type instances share the same copy of the data. Classes and closures are reference types, so assignment only adds a reference, but it does not copy the data. In fact, initialization of a reference type creates a shared instance that will be used by different instances of a reference type such as class or closure. Two variables of the same class type will refer to a single instance of the data, so if we modify the data in one of the variables, it will also affect the other variable. The following example presents a class with referencing:

class OurClass { 
var data: Int = 3
}

var referenceA = OurClass()
var referenceB = referenceA // referenceA is copied to referenceB
referenceA.data = 5 // changes the instance referred to by referenceA and referenceB
print("(referenceA.data), (referenceB.data)") // prints "5, 5"

As seen from the preceding example, changing referenceA.data also changes referenceB.data as they refer to the same shared instance.

This fundamental difference between value and reference types can have a huge impact on our system architecture. In functional programming, it is recommended to prefer value types over reference types as it is easier to trace and reason about value types. As we always get a unique copy of data and the data is not shared among instances, we can reason that no other part of our program is going to change the data. This feature of value types makes them especially helpful in multithreaded environments where a different thread will be able to change our data without informing us. This can create bugs that are very hard to debug and fix.

To be able to use this feature in Swift with classes, we can develop immutable classes using only immutable stored properties and avoiding exposing any APIs that can alter the state. However, Swift does not provide any language mechanism to enforce class immutability the way it enforces immutability for struct and enum. Any API user can subclass our provided class and make it mutable unless we define them as final and avoid open definitions. This is not the case with struct, enum, and tuples as basically we cannot subclass them.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset