Programming in Swift: Functions & Types

Jan 4 2022 · Swift 5.5, iOS 15, Xcode 13

Part 5: Protocols & Inheritance

45. Value vs. Reference Types

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 44. Challenge: Protocols Next episode: 46. Conclusion

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 45. Value vs. Reference Types

Update Notes: This course was originally recorded in 2019. It has been reviewed and all content and materials updated as of October 2021.

Transcript: 45. Value vs. Reference Types

Before I wrap up this course, I want to touch on a few lingering questions you might have about all of these named types.

Value vs. Reference

[Slide 01] A common big question is whether to use a structure or a class. This might also be phrased like “Should I use a value type or a reference type?”.

[Slide 02] Sometimes the frameworks you’re using decide for you. SwiftUI is built around Structures, whereas UIKit is class-based, so, it really isn’t up to you, there.

But you can, and probably will, still use structures and classes to model other things in your app, no matter which UI framework you use. When you’ve got more experience, and large data sets, you may find yourself choosing one or the other for performance reasons, but we won’t get into that here.

For most of your types, speed won’t need to be taken into consideration, and it’s not as simple as one being faster than the other. Normally, (while there are no hard and fast rules), there are some considerations which can help you to choose.

To help us visualize things, I’ve got a special guest: Jessy!

Structures are value types. If a structure instance holds the same values as another, consider them to be equal.

For example, these dumbbells weigh the same and they’re both in good condition. I don’t care which one of them goes in which of my hands if I’m doing an exercise.

[Slide 5]

But class instances have identity. They’re all unique – no two are considered to be the same even if all of their values are the same.

For example, these pairs of shoes, if modeled as value types, would be equivalent. Same color and size; the brand who makes them would probably tell you are the same “stock keeping unit”.

I really like these shoes, so when they were still available, I bought multiple pairs. This pair, I wear outside. But I don’t want to track dirt inside, so I leave them at the door. And when I want to wear shoes inside, I wear this pair.

To me, it’s important to be able to distinguish which pair is which, so I leave them in designated places in the house when I’m not wearing them. To keep my app as tidy as possible, I’d model a pair of these shoes as a class.

As we’ve gone over, the term “object” refers specifically to a class instance. And those work great, for representing physical objects. But maybe don’t tell people that you’re thinking of them as objects unless they’re also programmers.

In your Swift code, though, as we went over with the dumbbells, an instance of a structure might be enough to model a literal physical object. So don’t feel constrained by the traditional meaning of the term “object”.

If you can’t make up your mind, maybe start with a structure, and then switch to a class later. Classes have somewhat greater capabilities, and you might find you need them.

You can also convert from a class to a structure, if you ever find that you no longer need certain capabilities you once did. So don’t get too hung up on this.

To review: Structures are value types, and classes are reference types. An instance of a structure in conceptually a value. Class instances are objects with identity. Structures copy their values when used in a new place, but classes share their data. Structures are immutable when declared as constants, while class properties remain mutable.

What if you are going to use a Class? In this part, you’ve learned two ways for Classes to inherit some functionality: Class Inheritance (subclassing) and Protocol adoption. So, you might be wondering, “When should I subclass?”

There’s rarely a right or wrong answer to this, but I’ll explain some of the tradeoffs that can help you make the best decision for any particular case. Remember - you always have a choice. For example, using the Student and StudentAthlete classes you worked with…

…you might decide you can simply put all of the characteristics of StudentAthlete into Student. In reality, this could solve all of the use cases for your needs. A Student that doesn’t play sports would simply have an empty sports array, and you would avoid some of the added complexities of subclassing. So how do you choose? Let’s go over 5 concepts to help you decide When To Subclass!

The first concept to keep in mind is the single responsibility principle. This states that, in software development, it’s a best practice for each class to have only a single concern.

In Student and StudentAthlete, you might argue that it shouldn’t be the Student class’s job to encapsulate responsibilities that only make sense to student athletes.

The second thing to consider is type safety. Subclassing gives a separate type to the subclass, and that can give you some benefits in the form of type safety!

For example, you could make a sports Team class that can only store student athletes inside. If you didn’t subclass and only had Students, you wouldn’t be able to use the Swift compiler to enforce that restriction.

You can subclass a shared base class multiple times by classes that have mutually exclusive behavior. For example, let’s say you have different types of buttons in your app, like ImageButtons and TextButtons. They look completely different. All they share is the fact that they’re pressed.

You can see here how storing image and text — not to mention any other kind of button there might be — in the Button class would quickly become impractical.

It might make sense for Button to be concerned with the press behavior, and the subclasses to handle the actual look and feel of the button.

Extensibility

Sometimes you don’t actually have a choice. If you’re extending the behavior of code you don’t own, you may have to subclass. In that button example, it’s possible Button is part of a framework you’re using, and there’s no way you can modify or extend the source code to fit your needs.

When you’re developing iOS apps, this will be the case if you’re interacting with a class-based framework like UIKit, or many other frameworks Apple’s provided for you. In that case, subclass Button. You can add your custom subclass and use it with code that’s expecting an object of type Button.

The last important thing to consider is that classes and class hierarchies model what objects are. But what if the important thing is what objects can do? If your goal is to share behavior between types, you should consider using protocols instead of subclassing.

As with all of the other concepts we’ve gone over, you’ll start to develop a stronger sense for subclassing and protocol usage as you gain more experience.