 So can you tell me the difference between a class and a struct in Swift? If you've ever been in an iOS interview before, chances are you may have been asked that question at some point. In fact, it's a super popular interview question, and if you didn't know how to answer it, hopefully by the end of this video, you will know how. We are going to dive into an example comparing classes versus structs, but more importantly, reference types versus value types, the differences between the two, when to use one over the other, and some common pitfalls to watch out for. So let's open up an Xcode Playground and get started. In my example here, I have a class that I created called Programming Language Reference. And I have another class called Programmer Reference. And it's a very simple example. The Programmer Reference is basically a programmer. And the programmer knows one or many programming languages, so the programmer contains an array of languages. And that's the basic data structure for this tutorial. Inside of these arrays here, I have two different collections of languages. For a web stack, we have JavaScript, Ruby, PHP. And for a mobile stack, we have Swift, Kotlin, Java, and Objective-C. And so that's pretty basic. And at the very top, I have the exact same setup except implemented as a struct instead of a class. The arrays are arrays of structs instead of arrays of classes. All right, so let's start off with our first use case here. So we're going to start off creating an instance of one of these programmers. So we'll say create a mobile developer, right? And that looks something like this. So we'll just allocate a mobile developer. And I'm going to use the reference to denote between a struct and a class as we go through this because we'll do a side-by-side of each. And we're going to create a new programmer reference. It's going to take a stack of languages, so we'll give it the mobile stack, the mobile stack reference, or the class-based language array. So we start off like that, so far so good. And maybe we go along here and we print out every language that belongs to this mobile developer that they know. So we do it like mobile developer reference. Print the mobile developer knows language.name, and actually that's the programming stack. And we'll continue along in our example here. So I'm just going to print out a new line for readability purposes. And now we want to create a web developer. So let's say we do something in our code like this. We're like, OK, I'm going to create an instance of a programmer. I've already got this guy created here. I can just go ahead and do something like this, right? So our web developer reference equals mobile developer reference. We start off maybe printing out all of the languages that the web developer knows just to see what's going on here. So if I copy that code here, and now I'm just iterating through all of the web developer languages, he's going to have the same exact languages as the mobile developer because we haven't assigned him anything different. They're pointing to the same collection. So you see when I print, Swift, Kotlin, Java, Objective-C, same for both. So then I do something like this. I'm going to print another new line just for readability purposes. And let's scroll down a little bit here. And now I'm going to actually assign the web developer stack. So I'm going to do that's web developer reference dot programming stack equals web stack reference. That's the class or the reference-based web stack languages. And we'll go through it one more time and copy our little block of code here for printing. And we'll print them again, right? And actually make sure to update what the title is that's being printed in here. For the inside the web, we want to do the web developer knows this instead of the mobile. That's just because I copied it. So next, we also want to copy that for loop again for the mobile developer. And I'm going to just iterate through the languages that he knows. And we're just going to paste that right below the new line like that. And so all we're doing is just printing out, you know, again, each language that each developer knows. And let's run it and see what we get. So if you look down here, you'll see that the web developer knows JavaScript, Ruby, and PHP. Then if we look at that final for loop, we see that the mobile developer knows JavaScript, Ruby, and PHP. But if you look at the console logs from the very first log we printed, the mobile developer should know Swift, Kotlin, Java, and Objective C, not the web stack. So what happened? We didn't assign the web stack to the mobile developer. We assigned the web stack to the web developer, but it impacted the mobile developer. And so this is what happens in certain situations if you're careless and how you reassign variables that are reference-based. Now let's walk through this exact same scenario again, except instead of using classes, we're going to use the structs. So I'm going to do something like this. Bar mobile developer value equals programmer value. And value is using to differentiate the struct from the class. So we'll give that the mobile stack value or the collection of structs. Instead of doing all those initial prints, I'm just going to consolidate this down. So what we're going to do next is create the web developer exactly the same way we did from before. So var web developer value equals mobile developer value. And then what we're going to do again is assign the web stack to the web developer value or give him the structs collection of languages. So web developer value, programming stack value equals web stack value. And make sure you don't make the mistake of using the classes instead of the structs so that could mess up this example. Now to make this a little bit easier, I'm just going to go scroll up a little bit. And where we did the class-based for loops for the previous example, I'm just going to copy those, scroll back down, and paste them right below and just rename the variable. So instead of reference, this will be a web developer value dot programming stack value to use the structs. And then same thing for the second loop, mobile developer value dot programming stack value. Okay, and now let's print this out and see what it looks like in the console down below. So we run our program and we go to the very bottom here and we take a look at where we started printing. So now using the structs for the comparison, web developer knows JavaScript or BPHP after we do the assignment, we then print out the mobile developer stack again. And the mobile developer knows Swift, Kotlin, Java, and Objective C, which is what he should know. That's what we expect. And so we see here that when we use structs, the changing or the mutating of the web developer's programming stack had no impact on the mobile developer that we printed down below using structs. Now, using classes, we saw that it mutated or it changed the mobile developer's programming languages to be the web stack. Because when we go back up and we look at our final print statements from example one, the mobile developer knows JavaScript or Ruby and PHP. So now that we've seen that example in action, let's talk about why this is happening. I've been tossing around the language of value types and reference types regarding structs and classes without really explaining it. So I'm going to try to do that now. So when we talk about structs or what are they, structs are data structures that are value types, which means that the actual data that they hold, that the values are copied when the property or when the data structure is created. So each data structure has its own version of whatever properties that it was given. And so that's essentially what a value type is. It's a copy of the data that the data structure contains. Now, what are some examples of this? Examples of value types data structures in Swift extend beyond structs. In fact, enumed, int, float, bool, string, array, dictionary are all value type examples. And I'm not talking about like the NS1s or the NS string, but I'm talking about these Swift structures themselves, things you'd find in the Swift library. These are implemented as value types. Another thing to keep in mind is value types are allocated on the stack. So if that ever pops up in an interview question, you can also explain that. Now let's contrast that with classes, which are reference types. So we know classes are reference types. And basically that means that the values of the data that they hold are not copied when they are assigned to a variable or a constant, rather than a copy, the reference to the same existing instance is used. So the key point of this is that the data is not copied, but a reference to the same instance is used instead. You can think of it kind of like a pointer if you're used to more C-based languages. Under the hood, that's effectively what's going on. So you can also, if it ever pops up, you can say reference types are allocated on the heap. And I want to emphasize this whole not copied, because it's the most important part of what differentiates reference types and value types. And so basically what that means, and as we demonstrated, is it's possible to have two references that point to the same instance. So it's possible to have two references that point to the same instance. And basically changing the properties on one reference would also change those properties on the other reference since they both point to the same memory address. And we can actually see that in action, and I'll show you in a second how we can do that. So the other point we're just adding to this is that changing properties on one reference would also change properties on the other points to the same memory address. Now in Swift, there is a identity operator. So I'm going to scroll back up to my class example, the reference example from the first one. And right at the very second for loop there, I'm going to paste a code snippet that I had from another example. And basically let's just take a look at what we're doing here. So we're printing the memory address for the mobile developer reference. We are then printing the memory address for the web developer reference. And then we're doing a check. Does the mobile developer reference point to the same reference as the web developer? If they do, we print that they point to the same instance. Otherwise, we print that they don't. And let's run this right now and take a look at the log. So looking here, you can see that we get the hex values for the memory addresses for each of these instances. And it ends in 8cc40 for the web developer and for the mobile developer. So they both point to the same instance and that if statement is firing. And you can see right here that I like to think of it as a pointer because that's effectively what it is. We are pointing to a location in memory, this address. And by changing the property on one instance that points to this address, it will also impact any other instances that also are basically pointing to that memory address. Which is why we saw in that example where when we assigned the web developer stack, it also changed the mobile developer stack because they're both pointing to this same piece of memory. Now, how could we fix that if we were still using classes or reference-based types? What we could do as a workaround would be instead of doing this assignment here, which is the dangerous part, right? We could give it a new instance. So var web developer reference equals programmer reference and we'll do the web stack reference, right? So now we've just allocated or instantiated a new piece of memory and gave that to the web developer. So let's run this again. And now if we go back and look at the memory addresses, right? The mobile dev ends in db99c0. The web dev ends in db9a20, different memory addresses. So the else statement fires, they do not point to the same instance. And also if you scroll back up here, when we assigned the web developer stack, JavaScript, Ruby, PHP, for the class-based example, it had no impact on the mobile developer. So because they point to two different memory addresses and that's why that worked. So that's an example of what could happen if you haphazardly abuse reference-based types and do sloppy programming like this, where you're assigning a reference from another reference and you're using var instead of let, which lets you mutate things. You can get into situations where things are changing underneath your feet, underneath you, and you don't even realize it because it's at the memory address level. And it could cause catastrophic bugs that could take you hours, days, or weeks to debug. And so you finally figure out that, hey, the problem is it's much more subtle than it appears. If you use structs and value types wherever you can, and as much as you possibly can, you can avoid almost all of these pitfalls because the values are always copied. So they're always guaranteed to have their own unique memory address and you can never get in a situation with a value type where something like this can change underneath your feet. So let's wrap this up with some general guidelines. Prefer using structs and value types over reference types where possible. They are implicitly safer as we saw in that example, the structs were unimpacted by my reckless coding. Always use let instead of var, unless you have a good reason not to. So if we scroll back up to the very beginning here, and let's go and take a look at this data structure, right, the class, what I did initially was I injected in the initial programming stack and I assigned it here, self.programming stack. But the property on the class is a var, which means it can be changed. That's risky. That's where you can start running into problems, especially with reference types. And that's what we demonstrated. So had I changed this to a let and been a little more reasonable, and I try to run my playground again, it's not going to compile because it's going to say that the property cannot be assigned because it's a let constant, right? It's immutable unless you make it mutable by creating a var. So that is always use let unless you want something to change and it's intentional. And kind of like I touched on, prefer injecting dependencies through the initializer of a class or a struct instead of assigning a property directly. When you use this in combination with let, you will have a much safer code in general. So doing things like this, assigning the properties and storing it as a var, is incredibly dangerous and risky and reckless and it's going to cause all kinds of problems if you let code like that slip through into production code. Now a final note is going to be an Objective-C compatibility. Unfortunately, Swift value types like Swift enum and structs are incompatible with Objective-C. So if you have a Swift framework and an Objective-C client or an Objective-C app that needs to use a Swift framework, the Objective-C code is going to have compatibility problems without you creating workarounds. So you'll see a lot of the at OBJC or at OBJC members or all kinds of things added to make an Objective-C friendly enumeration so on and so forth. And it's unfortunate in the current state right now which is Swift 4. However, hopefully in the future, as Objective-C is kind of phased out over time, this will be less of a pain and are thrown in your side. But for right now, legacy compatibility, this is still an issue. So it's just something you have to keep in mind. And that wraps up this lesson. If this question ever pops up for you in an iOS interview in the future, you better nail it. But hopefully you realize a lot of the benefits and safety you get from using value types in your Swift code and reference types where you have to. If you found this tutorial helpful, you know what to do. Smash that like button and consider subscribing to Code Pro to stay up to date for all the latest tutorials. You can follow me on social media. You can find me on Facebook, on Twitter, and on Patreon. Patreon supporters get early access to all of my YouTube videos as well as access to source code for each tutorial. So if you want to support me on Patreon, there's a link for that in the description and you can support me there. Thank you so much for stopping by and I will catch you in the next one. Hey, if you made it this far, you should consider subscribing to Code Pro. Press that red subscribe button down below to be notified for all my future tutorials and content. Also, make sure to check out my Patreon page. Patreon supporters receive early access to future tutorials as well as access to source code for each YouTube tutorial and access to my full-length iOS development courses.