Stored and Computed Properties in Swift

Stored and Computed Properties in Swift
⏱ Reading Time: 7 mins

A concept that all developers meet early when start programming in Swift is about properties. This term is one of the most common ones that somebody reads, writes or talks about in programming articles, books, courses or discussions. Putting it in plain words, properties are variables and constants that store values, and that we declare in Swift classes, structures, and enumerations; nothing more. But properties are not unique to Swift; we meet them in every Object-Oriented Programming (OOP) language.

Regardless, two new terms are getting into the play around properties soon enough; stored and computed. Even though both explain their meaning somehow, one realizes what they actually are only after has explored them.

It often occurs programmers to be writing code without even having heard about the existence of these concepts. It’s a fact that we can write entire apps without knowing the slightest detail about those. So, why is it necessary to learn about them?

Well, first of all, since stored and computed properties exist as concepts in the Swift language, they become a must-have knowledge that everybody should be understanding and possess. After all, and as you will find out in this post, it’s not a difficult topic. But further than that, knowing what they are all about and what they have to offer in extend, can help us change the way we code and gain better programming habits.

So, let’s dive together into some more details about stored and computed properties in Swift, highlighting them through a few simple examples and explanations.

Stored Properties

Stored properties are variables or constants that store values to instances of classes or structures. Even though it sound obvious, values assigned to variables can be modified at any time. On the contrary, values originally assigned to constants cannot be altered at a later time.

Depending on the needs of the program we implement, we may assign default values to properties along with their declaration. If there are properties with just their data type, no default value, and not declared as optionals, then initial values should be provided during the initialization of the instance of the type they belong to. Note that for stored properties that are constants, the default or initial value is what the property will be containing for the entire lifetime of the instance; constants are immutable and don’t change. Also, we can declare stored properties as optionals.

The following code snippet demonstrates all that:

In the Programmer class above, there are four stored properties declared. The name property is of type String, and does not have a default value; that means that it will be necessary to provide one when we’ll initialize an instance of the class.

The language property that’s supposed to keep the programming language that the programmer is experienced in, is a constant. Similarly to the previous one, this stored property will get its value at the initialization time of the instance, but in contrast, it won’t change after that.

The yearsOfExperience property is declared with a default value. Since it’s a variable, we can modify its value whenever we want later in the future. Also notice that we don’t set an explicit type to the property, even though it would be perfectly fine if we would have done that. It is automatically inferred from the original value assigned to it.

Finally, the secondLanguage property is an optional, and it’s supposed to store another programming language that the programmer is acquainted with.

Once again, all of them are stored properties, as they can store values that are part of the instance of the class. In the above example there is a mix; properties with and without default values, and one that is optional.

If we keep the above implementation as is, then the first two stored properties will make Xcode show an error saying that the class has no initializers. In cases like that where the container type is a class, it’s required to implement a custom initalizer, where we will assign initial values to these properties:

Let’s create a Programmer instance now, to see the above stored properties in action. The first two properties will get a value upon initialization:

Since name is a variable, we can change it whenever we’d like to:

However, we can’t do the same with the language stored property. It’s a constant, so it’s immutable:

Regarding the other two stored properties, we can assign values to them whenever that’s appropriate to do:

And because they are variables, we can freely alter them when necessary. The last one especially can also become nil; it was declared as an optional variable.

Stored properties in structures

Just a few lines earlier we initialized a Programmer instance and assigned it to a variable using the var keyword. We could have used let and assign the instance to a constant as well; we can still use all stored properties as shown above already:

However, things would not be the same if Programmer was a structure instead of a class:

In this case where Programmer is a structure, a default initializer is automatically provided; therefore we can simply skip implementing a custom one as demonstrated earlier with the class.

Initializing now a Programmer instance and assigning to a variable will work exactly as expected without any issues. But the following line that assigns the instance to a constant declared with the let keyword triggers an error in Xcode:

Just because the Programmer structure is a value type, all of its stored properties are also becoming constants similarly to the programmer instance. That happens regardless of whether we declared most of them as variables. That’s not the case though with classes; they are reference types, and variables of an instance can be modified, even if the instance has been assigned to a constant.

So, as a rule of thumb, assign instances of structures to variables in order to mutate stored properties. On the other hand, feel free to assign instances of classes to either variables or constants. The former is mandatory in case you want to make the instance nil at some point in the future.

Computed Properties

In contrast to stored properties, computed properties do not store any values. What they do, however, is to return and optionally set the value of other stored properties, usually after some calculations.

In order to do that, they provide a getter and a setter for fetching and storing values respectively. To make that clear, take a look at the following structure:

The Angle structure has a stored property called degrees for storing an angle in degrees. But we can also express an angle in radians, so Angle structure defines the rads property as well. This is not a stored, but a computed property.

The most noticeable thing in rads property is its getter and setter. Inside the body of rads that’s defined by the curly brackets, there is a get and a set block respectively. In the first one, the returned value is the radians after having been calculated based on the current value of the degrees property. In the setter, we convert the given radians value to degrees and store it to the degrees stored property.

See that the radians value in the setter above is represented with the newRads name. Providing it, however, is not mandatory, as there is a shorthand to use; we can omit it, and in that case we can access the new value with the newValue default name:

As you can realize, what we managed to do above is to represent an angle in two different ways; both in degrees and radians. But even though we declared two properties, just one of them actually stores a value. The other calculates its value on the fly, and when set, provided radians are converted and stored as degrees. That clearly demonstrates the convenience and the power that computed properties offer; no further additional action is necessary in order to convert degrees to radians, or the opposite.

Read only computed properties

Implementing the getter of a computed property is mandatory. However, doing so for the setter is absolutely optional, and it depends on the computed property we are defining.

To see an example of that, suppose that we have a structure to keep temperature values. For that purpose, we have an array, and a computed property to get the average temperature value:

Notice that no setter exists here; and it wouldn’t make sense if it existed. In cases like the above where there is no setter, then the computed property is called read only.

The way we write read only computed properties can be simplified by getting rid of a couple of things. The first one is the get body; since there is no setter, it’s not longer necessary to explicitly write it:

The second move towards making the read only computed property “lighter”, is by removing the return keyword. Keeping it in single statements is not mandatory:

The computed property is simpler now, as the explicit getter and the return keyword are missing from the implementation.

Computed properties instead of methods

It’s quite common to see computed properties being implemented in place of methods, as long as no arguments are necessary to be provided. And the last example right above can help make that clear.

Suppose for a moment that the average computed property does not exist in the Temperatures structure. However, the requirement to get the average temperature still exists. Normally, we would implement a method to get that value like so:

Even though the differences are little in terms of syntax, it’s probably more convenient and a bit simpler to get the average temperature as a computed property, instead of defining a method. In fact, both ways are correct, and so it’s mostly a matter of a coding habit. But since computed properties can often have the same results to methods, and given that they are syntactically simpler, the gain here would be less, clearer, and more readable code.

There is one last thing to note regarding computed properties. Similarly to methods where we specify the return type, it’s also necessary to explicitly set the type of the computed property. That’s not the case with stored properties; as mentioned previously, the type there can be inferred based on the default value assigned to the property.

Conclusion

The exploration on stored and computed properties ends here, and this post summarizes pretty much everything you need to know about them. It’s quite probable that you have already known many of the presented topics even out of experience; especially about stored properties, as that’s what we all mostly use. Computed properties on the other hand are interesting too, as besides their original purpose, can also be used in place of methods. I hope that you’ve learnt something new here today, especially if you are a newcomer in Swift. Nevertheless, thank you for reading, and stay tuned for other interesting topics to come!

This post has also been published on Medium.

If you found this post useful then please consider sharing it! Also, subscribe to my newsletter in order to be notified about everything new published here directly in your inbox, and follow me on Twitter, on YouTube, on Medium and other social media.