The other day, I was chatting with some colleagues, who were interviewing people for a Swift Dev job opening. They said the killer question was, what’s the difference between a ‘struct’ and a ‘class’?. I was surprised. That’s something every swift developer should know. For that reason, I decided to write this post.
Imagine a reference as a link to a value. With a reference, we access the data. Instances of a class are called “objects”, and you cannot directly assign them to a variable, you reference it.
The most common way to create a reference type in Swift is using a
Unlike the value types, references do change their referenced value when the assigned variable is mutated.
Even when a reference is assigned with
let, we can still modify properties in the referenced object.
That means that the constant is the reference, not the object. With value types we wouldn’t be able to do this.
Trying to change the value of b in
myValue.b = 8 would result in a compiler error.
Now let’s complicate things a little. Let’s create a value type that contains a reference type.
aValue maintained it’s original value in
aReference.aValueProperty changed for both the original and the copied value, even when it was only modified in the copy.
This behaviour is what we call a “shallow copy”, where we copy all the values but the referenced value stays the same. This is because we only copied the references. On the other hand, when we copy absolutely everything, including the referenced values, we call this a “deep copy”.
This may be a little confusing, so take your time to understand it.
When we use the equals operator (
==), we are checking if two values are the same.
The same behaviour doesn’t occur when comparing custom value types.
This behaviour happened because
AnotherValueType doesn’t implement the
Equatable protocol, but that’s a topic for another time.
The same happens for reference types. What we can do with reference types is check if they are the same with the
=== operator checks if two references point to the same value.
Surprise! Yes, functions are reference types.
You can assign them to variables:
You can pass them as parameters:
They are one of the most relevant features of Swift.
These kinds of functions that receive another function as a parameter are called “higher order functions”. Some famous ones are:
filter, among others.
Functions can be declared inside other functions, like in a for-loop or inside many other scopes. But since functions are reference types when they are declared inside another scope and passed further, after the local scope ends, the local variables used inside the function aren’t destroyed.
The functions that hold variables outside of their scope are usually called closures. But it doesn’t mean that other functions declared with
func aren’t also closures.
Having a good understanding of how types work in Swift will help you decide when to use what, and more significantly, to better architect your apps.
Please, let me know your thoughts and questions.