0 1 00:00:01,300 --> 00:00:09,160 Now, in the last lesson, we spoke about the theory part of structs versus classes and we talked about value 1 2 00:00:09,160 --> 00:00:11,620 types versus reference types. 2 3 00:00:11,620 --> 00:00:18,070 Now, in this lesson, I want to show you using real-life examples just what all of that means. 3 4 00:00:18,100 --> 00:00:25,090 So we're going to create a new project inside Xcode so that we don't mess up our calculator app and 4 5 00:00:25,150 --> 00:00:32,340 you're going to head into the mac tab and choose the Command Line tool, and go ahead and click Next. 5 6 00:00:32,350 --> 00:00:36,910 Now, I'm going to call this simply just Structs vs. Classes 6 7 00:00:37,270 --> 00:00:40,600 and I'm going to save this somewhere on my desktop. 7 8 00:00:40,690 --> 00:00:42,700 So we've worked with Mac 8 9 00:00:42,760 --> 00:00:44,360 Command Line Tools before 9 10 00:00:44,560 --> 00:00:50,920 and you know that there is a Main.swift which is the entry point and all of the code here gets called 10 11 00:00:50,920 --> 00:00:52,340 in sequential order, 11 12 00:00:52,630 --> 00:00:57,930 and this kind of structure allows us to create multiple files that we can tap into, 12 13 00:00:57,940 --> 00:01:01,740 so I can show you the differences between structures and classes. 13 14 00:01:01,750 --> 00:01:09,190 Now, I'm firstly going to delete that print statement and I'm going to create a brand-new Swift File 14 15 00:01:09,490 --> 00:01:14,450 inside the same folder and it's going to be called ClassExample. 15 16 00:01:15,100 --> 00:01:19,540 Then I'm also going to create something called StructExample. 16 17 00:01:20,320 --> 00:01:25,470 And now I have my two files where I will show you what structs and classes do. 17 18 00:01:25,570 --> 00:01:33,670 So, now we can head over to our class example and we're going to create a brand-new class. 18 19 00:01:33,700 --> 00:01:36,590 Now, this class is going to be called a Superhero 19 20 00:01:37,120 --> 00:01:43,330 and it does not inherit from any other superclasses. It's just an independent class. 20 21 00:01:43,330 --> 00:01:46,750 Now, this class superhero is going to have two properties. 21 22 00:01:46,750 --> 00:01:51,910 One is going to be called name and it's going to be a String and the other is the universe where the 22 23 00:01:51,910 --> 00:01:53,500 Superhero is from, 23 24 00:01:53,500 --> 00:01:55,720 and this is also going to be a String. 24 25 00:01:56,080 --> 00:02:03,580 Now, at this point, we're pretty used to this error which says, "Class 'Superhero' has no initializers," are two 25 26 00:02:03,580 --> 00:02:07,470 stored properties name and universe, 26 27 00:02:07,580 --> 00:02:11,540 both don't have any initial values. And swift, 27 28 00:02:11,560 --> 00:02:16,260 remember, always needs initial values even if it has to be nil. 28 29 00:02:16,270 --> 00:02:23,000 So in this case, I'm not turning any of these into nil by turning this into a optional String. 29 30 00:02:23,020 --> 00:02:30,420 No, I'm actually going to initialize it. So to initialize it, we can write the designator init, 30 31 00:02:30,730 --> 00:02:32,120 and in this init, 31 32 00:02:32,170 --> 00:02:39,150 so whenever we try to create a new object from the Superhero class, we're going to provide a name that's 32 33 00:02:39,310 --> 00:02:45,130 in the form of a String and the universe in the form of a string. 33 34 00:02:45,130 --> 00:02:52,390 Now, when we initialize the class with those values, then we're going to set this class' name property to 34 35 00:02:52,390 --> 00:02:56,830 equal that local name variable, 35 36 00:02:57,010 --> 00:02:59,600 and we're going to do the same with our universe. 36 37 00:03:04,200 --> 00:03:11,770 Now, all of this should be familiar to you because in the intermediate Swift classes, we spoke about designators 37 38 00:03:11,790 --> 00:03:17,940 initializers, convenience initializers, and what it means to create new objects from classes. 38 39 00:03:18,120 --> 00:03:24,600 So if you need a brief refresher, feel free to head over there and just revise those sections before 39 40 00:03:24,600 --> 00:03:30,410 you come back because I'm going to assume that you've understood how to initialize a class. 40 41 00:03:30,480 --> 00:03:37,710 So, now that we've created our class, then we can quite easily, in another file, create an object from that 41 42 00:03:37,710 --> 00:03:38,390 class. 42 43 00:03:38,430 --> 00:03:45,850 So let's create a constant called hero and it's going to be equal to a new instance of a Superhero. 43 44 00:03:46,110 --> 00:03:52,320 And when I tried to initialize it, you can see that the initializer requires that I give those two stored 44 45 00:03:52,320 --> 00:03:54,070 properties a value. 45 46 00:03:54,360 --> 00:03:57,040 So let's call it, I don't know, "Iron Man," 46 47 00:03:57,330 --> 00:03:59,070 and he's from the "Marvel" universe. 47 48 00:03:59,310 --> 00:04:07,390 Okay, so this is how I've created my class and this is how I've initialized my object from that class. 48 49 00:04:07,410 --> 00:04:16,200 Now, if I was to go into my StructExample and create that Superhero class as a struct instead, then I 49 50 00:04:16,200 --> 00:04:23,990 would simply replace the word class with struct, and the struct also has to have a name that's capitalized. 50 51 00:04:24,240 --> 00:04:31,500 Now, if I tried to call this Superhero as well, then you can see that Xcode gives me an error and it 51 52 00:04:31,500 --> 00:04:35,440 says, "Invalid redeclaration of 'Superhero.'" 52 53 00:04:35,850 --> 00:04:43,640 Now, even though, in this case, this is a superhero struct and, in this case, this is a Superhero class. 53 54 00:04:43,770 --> 00:04:52,410 The Swift compiler doesn't actually let you get the same name to struct classes or enums, so I can't 54 55 00:04:52,410 --> 00:04:56,020 create a enum called Superhero either. 55 56 00:04:56,130 --> 00:04:59,890 This is all forbidden, so I have to give it unique names. 56 57 00:04:59,970 --> 00:05:05,880 So let's change our class Superhero to be called ClassHero, 57 58 00:05:06,240 --> 00:05:08,710 and, of course, we have to change it here as well. 58 59 00:05:09,970 --> 00:05:14,760 And then, inside our struct, I'm going to call this a StructHero, 59 60 00:05:15,050 --> 00:05:19,860 and now all of our errors will go away and we can continue creating StructHero. 60 61 00:05:20,150 --> 00:05:23,130 So, again, this struct is going to have two properties, 61 62 00:05:23,370 --> 00:05:31,400 name which is a String, and also universe which is also going to be a String. 62 63 00:05:31,400 --> 00:05:38,600 Now, in this case, you'll notice that no matter how much I try to refresh or command B or run, you can 63 64 00:05:38,600 --> 00:05:45,170 see that I don't get any errors, even though I also don't have any initializers inside my struct, whereas 64 65 00:05:45,260 --> 00:05:51,650 with our class if I didn't have these few lines of code, then Xcode very quickly starts screaming that 65 66 00:05:51,770 --> 00:05:58,040 ClassHero has no initializers because these two stored properties need values and, therefore, I need 66 67 00:05:58,040 --> 00:05:58,580 initializer. 67 68 00:05:58,740 --> 00:06:03,390 Well, in structs, you actually get a free initializer. 68 69 00:06:03,440 --> 00:06:12,050 So down here, if I try to create a new hero that's a new instance of the StructHero, you can see that 69 70 00:06:12,050 --> 00:06:16,100 as soon as I tried to initialize it, I get an initializer, 70 71 00:06:16,220 --> 00:06:22,070 and this is created behind the scenes every single time you create a struct which makes life just a 71 72 00:06:22,070 --> 00:06:25,430 little bit easier for you when you're creating these structures. 72 73 00:06:25,430 --> 00:06:29,430 So, now that we've seen how you can initialize structs and classes, 73 74 00:06:29,450 --> 00:06:32,290 I'm going to delete these two lines of code, 74 75 00:06:33,970 --> 00:06:40,930 and we're going to head into our main.swift. Now, over here, I'm going to create a new hero which is 75 76 00:06:40,930 --> 00:06:50,170 going to be a ClassHero and I'm going to initialize it as "Iron Man" from the "Marvel" universe. 76 77 00:06:50,260 --> 00:06:57,550 Now, at this point, if I needed another Marvel hero, then it might seem that I could just say anotherMarvelHero 77 78 00:06:57,790 --> 00:07:00,860 is equal to the hero. 78 79 00:07:01,030 --> 00:07:08,440 And I make a copy of this hero which is initialized to have Iron Man as the name and Marvel as the universe, 79 80 00:07:08,980 --> 00:07:17,130 and then all I do is I change my anotherMarvelHero and I only change its name, and I call it "The Hulk." 80 81 00:07:18,370 --> 00:07:26,830 Now, because our hero already has Marvel set as the universe, then my anotherMarvelHero, just by copying 81 82 00:07:26,830 --> 00:07:27,960 over that hero, 82 83 00:07:28,060 --> 00:07:31,360 then it seems like I would have that same universe already, 83 84 00:07:31,570 --> 00:07:35,020 and all I need to do was just to change its name. 84 85 00:07:35,020 --> 00:07:40,260 Now, if we go ahead and do some print statements just to see what those values are, 85 86 00:07:40,360 --> 00:07:48,460 so let's say, here name equals, and we'll use string interpellation to tap into hero.name and 86 87 00:07:48,550 --> 00:07:58,780 we'll also at the same time print "anotherMarvelhero name is equal to anotherMarvelHero.name. 87 88 00:07:58,780 --> 00:08:05,650 So let's go ahead and run this. And I want you to predict what will be the results for each of these 88 89 00:08:05,650 --> 00:08:07,960 print statements. 89 90 00:08:07,960 --> 00:08:11,290 All right, so that is the result that we got back. 90 91 00:08:11,290 --> 00:08:17,440 We've got hero name = The Hulk, anotherMarvelhero name = The Hulk. 91 92 00:08:17,440 --> 00:08:21,550 Wait a minute, there has to be something that's wrong here, right? 92 93 00:08:21,550 --> 00:08:24,020 I didn't change the name for hero. 93 94 00:08:24,040 --> 00:08:27,340 I never said hero.name = The Hulk. 94 95 00:08:27,400 --> 00:08:29,530 What is this all about? 95 96 00:08:29,530 --> 00:08:31,970 This is not what I predicted at all. 96 97 00:08:32,290 --> 00:08:36,910 Well, this is a good example of a reference type behavior. 97 98 00:08:37,210 --> 00:08:45,700 Now, when I made a copy of hero and I assigned that copy to something called anotherMarvelHero, 98 99 00:08:46,030 --> 00:08:54,010 what actually happened behind the scenes is I simply created a new reference to the same object. 99 100 00:08:54,250 --> 00:09:03,910 And when I changed a property on my new reference, it also changed the property of that same object which 100 101 00:09:03,970 --> 00:09:08,630 both anotherMarvelHero and hero refers to. 101 102 00:09:08,640 --> 00:09:14,400 Now, remember how we said that structs were value types and classes were reference types. 102 103 00:09:14,620 --> 00:09:21,480 And when I create a new copy of a struct, I just copy over the values to a new thing. 103 104 00:09:21,580 --> 00:09:29,970 But when I copy a reference type, then I simply create a new reference to the same thing, 104 105 00:09:30,070 --> 00:09:33,780 and the actual object is not copied at all. 105 106 00:09:33,850 --> 00:09:38,330 There's still only one blue folder that contains all of that data. 106 107 00:09:38,350 --> 00:09:46,660 So whereas with the structs, when we make a new copy of the struct, we end up with two copies each having 107 108 00:09:46,660 --> 00:09:50,470 separate values that can be changed separately from each other. 108 109 00:09:50,680 --> 00:09:57,340 But when we copy reference types such as classes, then what we end up doing is we don't actually copy 109 110 00:09:57,400 --> 00:10:03,260 the object with all the data. We just copy the reference to the object 110 111 00:10:03,400 --> 00:10:10,180 and this means that we now have two references to the same object. And when we tried to change a hero or when 111 112 00:10:10,180 --> 00:10:15,240 we tried to change anotherMarvelHero, they're both changing the same thing 112 113 00:10:15,520 --> 00:10:18,220 and it can get very confusing very quickly. 113 114 00:10:18,340 --> 00:10:23,770 You can imagine that as your app gets more complex, you can end up with objects that are reference from 114 115 00:10:23,770 --> 00:10:30,670 lots of different places all trying to modify the same object, and you will end up with really unexpected 115 116 00:10:30,680 --> 00:10:36,490 behavior and you will lose track of which reference is changing which object, and end up with a whole 116 117 00:10:36,490 --> 00:10:40,240 lot of complexity and an app that's very difficult to debug. 117 118 00:10:40,270 --> 00:10:47,200 Now, whenever I think about this problem of multiple references to the same object, I think about Black 118 119 00:10:47,200 --> 00:10:53,440 Friday sales and people fighting each other for the same objects all trying to grab it and buy it. 119 120 00:10:53,560 --> 00:10:57,270 And as you can see, there's a lot of mayhem that ensues. 120 121 00:10:57,280 --> 00:11:03,970 So if we head back into our code where we show that unpredictable behavior previously, whereby changing 121 122 00:11:04,030 --> 00:11:10,510 anotherMarvelHero's name, we actually ended up changing the original hero's name as well. 122 123 00:11:10,780 --> 00:11:20,230 Well, let's go ahead and change this hero from a class hero to a StructHero using our struct blueprint in 123 124 00:11:20,230 --> 00:11:22,430 the struct example file. 124 125 00:11:22,450 --> 00:11:24,900 Well, now when we create a copy of the hero 125 126 00:11:25,150 --> 00:11:27,070 that's called another Marvel hero, 126 127 00:11:27,370 --> 00:11:35,600 when we change the name of anotherMarvelHero to "The Hulk," it won't affect our original hero's struct. 127 128 00:11:35,690 --> 00:11:38,900 So let me press play and show you what the results looked like. 128 129 00:11:39,070 --> 00:11:47,140 You can see that our hero name is Iron Man, just as we intended, and our anotherMarvelHero name is "The Hulk" 129 130 00:11:47,440 --> 00:11:49,220 just as we intended as well. 130 131 00:11:49,420 --> 00:11:52,600 And this is why structs are much simpler 131 132 00:11:52,600 --> 00:11:59,530 which means that it's easier to create a larger app with less complexity. And you can imagine that if 132 133 00:11:59,530 --> 00:12:05,800 you're coding on the same project with lots of different people or sometimes even if my code with me 133 134 00:12:05,980 --> 00:12:10,270 and me in six months, me in six months is like a random person. 134 135 00:12:10,300 --> 00:12:12,440 She doesn't remember how the code works. 135 136 00:12:12,490 --> 00:12:18,270 She doesn't remember which things can be changed, which things shouldn't be changed, what the effects are, 136 137 00:12:18,380 --> 00:12:21,270 and so we have to safeguard against all of that. 137 138 00:12:21,320 --> 00:12:27,650 We have to try and make everything as least error prone as possible, so that you guard against other 138 139 00:12:27,650 --> 00:12:31,130 people or future you messing up your code. 139 140 00:12:31,130 --> 00:12:36,060 Now, here's another example of when reference types can really hurt you. 140 141 00:12:36,110 --> 00:12:42,680 Let's say that I create a new hero initialized from our ClassHero again and I create a new array called 141 142 00:12:42,740 --> 00:12:43,560 avengers. 142 143 00:12:43,580 --> 00:12:50,110 Now, inside my array, I'm going to include my first hero as well as my anotherMarvelHero. 143 144 00:12:50,330 --> 00:12:54,670 So, now I have an array with two class hero objects. 144 145 00:12:54,890 --> 00:13:02,420 And at some point, I realized that actually my avengers, I'd really prefer the first avenger to be "Thor" 145 146 00:13:02,450 --> 00:13:03,250 instead. 146 147 00:13:03,320 --> 00:13:09,380 So I know that I've created this brand-new Avengers array with some heroes inside, but I'm going to change 147 148 00:13:09,380 --> 00:13:14,740 that array's first item to have a different name and call it "Thor." 148 149 00:13:15,080 --> 00:13:23,630 So, now if I go ahead and print my "first avenger name," now what do you expect to happen? 149 150 00:13:23,660 --> 00:13:28,000 Did you expect that all three heroes now all have the name Thor? 150 151 00:13:28,220 --> 00:13:35,610 Or did you expect that we'd be changing the actual array, rather than all of the referenced objects? 151 152 00:13:35,720 --> 00:13:43,880 Well, in this case, our avengers, it's actually an array of references. And whenever we change anything 152 153 00:13:43,910 --> 00:13:50,900 about our array, we're actually not changing the array. We're changing the underlying object which is shared 153 154 00:13:50,900 --> 00:13:54,660 between this array, this object, and this object. 154 155 00:13:54,770 --> 00:13:57,880 And so now all three of them have the name Thor. 155 156 00:13:57,920 --> 00:14:03,770 Now, again, we can fix this by simply reverting back to a simple struct. 156 157 00:14:04,130 --> 00:14:10,240 And in this case, everything that we assumed is now exactly what happens. 157 158 00:14:10,250 --> 00:14:15,510 Our hero is still called Iron Man and our anotherMarvelHero is now called the Hulk, 158 159 00:14:15,800 --> 00:14:19,060 and our first avenger's name is now Thor. 159 160 00:14:19,190 --> 00:14:22,410 And this is one of the biggest benefits of struct. 160 161 00:14:22,580 --> 00:14:27,260 They make everything a lot more predictable, a lot simpler, 161 162 00:14:27,320 --> 00:14:32,750 instead of having these references all over the place pointing to different objects that sometimes might 162 163 00:14:32,750 --> 00:14:38,480 collide, and you might have a different class that changes your objects without you expecting it, too. 163 164 00:14:38,480 --> 00:14:39,340 Well, with struct, 164 165 00:14:39,380 --> 00:14:42,690 it's a lot more straightforward and it's a lot simpler. 165 166 00:14:42,920 --> 00:14:48,870 Now, another problem with class objects is how we deal with immutability. 166 167 00:14:48,980 --> 00:14:51,410 So I'm going to delete all of this code 167 168 00:14:51,440 --> 00:14:57,960 other than our initial initialization code. And I'm going to create a new instance of a class hero. 168 169 00:14:58,340 --> 00:15:03,180 But instead of creating it as a variable, I'm going to create it as a constant. 169 170 00:15:03,470 --> 00:15:08,620 So now I have this constant which is called hero which is of type 170 171 00:15:08,620 --> 00:15:09,510 class hero. 171 172 00:15:09,620 --> 00:15:17,010 Now, what do you think will happen when I try to change the name property of my constant hero? 172 173 00:15:17,120 --> 00:15:24,170 So we all know that constants get a value assigned only once and they cannot be changed, 173 174 00:15:24,260 --> 00:15:30,960 right? Well, then why is it possible to do this? 174 175 00:15:32,310 --> 00:15:38,790 And I'm not getting any errors at all from Xcode, this is perfectly legal to do. 175 176 00:15:39,150 --> 00:15:47,790 Well, the reason is because in our ClassHero class, you can see that we created name and universe as 176 177 00:15:47,790 --> 00:15:51,090 properties that are variables. 177 178 00:15:51,360 --> 00:15:58,770 And this means that even though we create a constant called hero, the only part of it that's constant 178 179 00:15:59,010 --> 00:16:04,850 is that we can simply reassign it to a new class hero object. 179 180 00:16:04,890 --> 00:16:06,860 We can't do this, right? 180 181 00:16:06,870 --> 00:16:10,320 This is what the "let" is preventing us from doing. 181 182 00:16:10,590 --> 00:16:15,760 But it does let us change everything else about our object hero. 182 183 00:16:15,960 --> 00:16:17,570 I can change the name. 183 184 00:16:17,700 --> 00:16:19,630 I can change the universe. 184 185 00:16:19,650 --> 00:16:21,240 Now, that's not right, 185 186 00:16:21,270 --> 00:16:26,880 right? Now, the whole reason why we create things as constants is to make it immutable, 186 187 00:16:26,940 --> 00:16:33,450 make sure that the future me or somebody else on my team can accidentally change something that shouldn't 187 188 00:16:33,750 --> 00:16:34,920 be changed, 188 189 00:16:34,950 --> 00:16:35,430 right? 189 190 00:16:35,580 --> 00:16:44,100 So this is another reason why you might use structs. Because if this was a struct instead, then we will 190 191 00:16:44,100 --> 00:16:46,320 get true immutability. 191 192 00:16:46,650 --> 00:16:53,760 And you can see that Xcode now gets angry even when we try to change one of its properties because hero 192 193 00:16:54,030 --> 00:16:58,340 is a constant now and it has true immutability. 193 194 00:16:58,350 --> 00:17:03,680 It cannot be changed after it was created because it has that "let" keyword, 194 195 00:17:03,810 --> 00:17:07,190 and also because the underlying thing is a struct. 195 196 00:17:07,290 --> 00:17:11,460 And this is because a struct, remember, is a value type. 196 197 00:17:11,460 --> 00:17:19,110 So when you change it, you actually have to create a whole new copy, and that "let" keywood is not letting 197 198 00:17:19,110 --> 00:17:19,940 us do that. 198 199 00:17:19,950 --> 00:17:27,630 So none of it can be changed if it is declared as a "let" constant which is, again, kind of what you would 199 200 00:17:27,630 --> 00:17:28,360 expect, 200 201 00:17:28,350 --> 00:17:28,650 right, 201 202 00:17:28,650 --> 00:17:34,230 when you make something immutable. The previous behavior when we were able to change lots of things about 202 203 00:17:34,230 --> 00:17:40,140 our hero without any warnings at all can potentially lead to a lot of unexpected errors. 203 204 00:17:40,140 --> 00:17:47,580 Now, the last thing I want to show you about structs is if inside our struct we created a function and 204 205 00:17:47,580 --> 00:17:50,120 it's called reverse name, 205 206 00:17:50,490 --> 00:18:03,000 and this function returns a String, and what it does is it takes the name, so self.name, and it calls 206 207 00:18:03,120 --> 00:18:06,180 the function reverse, 207 208 00:18:06,180 --> 00:18:12,540 and what this does is it will return an array containing the elements of the sequence in reverse order. 208 209 00:18:12,690 --> 00:18:20,140 So that means that if our name was Hulk, then what we'll get back is K-L-U-H. 209 210 00:18:20,340 --> 00:18:29,880 But the only problem is that this returns a collection, a reversed collection, and it's not a String, 210 211 00:18:29,880 --> 00:18:36,250 so we have to cast it into a String if we want to be able to return this as a String. 211 212 00:18:37,300 --> 00:18:46,930 So, now if we head over to main.swift and we say, hero.reverseName, and let's go ahead and print 212 213 00:18:47,440 --> 00:18:57,250 the output of this function call into our debug, and you can see we get "naM norI" which is the reverse 213 214 00:18:57,310 --> 00:18:58,660 of Iron Man. 214 215 00:18:58,870 --> 00:19:09,450 Now, so far so good. But what if our method inside our struct was trying to change one of its properties instead? 215 216 00:19:09,790 --> 00:19:22,640 So let's get rid of this output and make this function rename self,name to equal self.name.reversed. 216 217 00:19:22,660 --> 00:19:29,790 Now, when you try to change a property inside a struct, Xcode will give you an error, 217 218 00:19:29,950 --> 00:19:37,170 and this is because whenever you try to change a structure, you have to create a new copy. 218 219 00:19:37,180 --> 00:19:44,380 And so if your method is going to change something about the structure, say, one of its properties to 219 220 00:19:44,380 --> 00:19:52,370 have a different value, then we have to mark this function that has that capability with the keyword 220 221 00:19:52,480 --> 00:19:54,020 "mutating." 221 222 00:19:54,310 --> 00:20:01,990 And this tells the Swift compiler that, Hey, watch out, this method is capable of changing the structure." 222 223 00:20:02,110 --> 00:20:07,930 So that means that when this method is run, we need to create a brand-new copy of this structure, and 223 224 00:20:07,930 --> 00:20:12,340 this is why you see this keyword "mutating" all over the place 224 225 00:20:12,340 --> 00:20:20,430 when you start working with struct. So structs are really, really cool and they're very, very useful, and 225 226 00:20:20,430 --> 00:20:27,320 the simple things that are predictable which will make your code less prone to errors and to bugs. 226 227 00:20:27,370 --> 00:20:35,200 So I recommend that whenever you're creating a new data model to go for a struct, instead of a class, 227 228 00:20:35,530 --> 00:20:39,610 if you want to create a better architecture for your app. 228 229 00:20:39,790 --> 00:20:47,640 Now, there is just one thing that struct can't do and you have to be aware of, the can't subclass. 229 230 00:20:47,650 --> 00:20:55,030 So, for example, if I wanted to create a struct that was a subclass of an NSObject, for example, then I 230 231 00:20:55,030 --> 00:21:02,070 will get a error: Non-class type 'StructHero' cannot inherit from class an 'NSObject.' 231 232 00:21:02,140 --> 00:21:07,100 You don't get inheritance from struct. If you need inheritance, 232 233 00:21:07,180 --> 00:21:09,610 you have to make a class. 233 234 00:21:09,610 --> 00:21:16,240 And this also means that when you're working with Objective-C objects and you want to be able to subclass 234 235 00:21:16,240 --> 00:21:23,620 them or work with them, then you also can't use struct because in Objective-C, the structs are very different 235 236 00:21:23,860 --> 00:21:25,120 to the Swift struct. 236 237 00:21:25,180 --> 00:21:31,750 The structs in Swift is almost like an eight-legged insects, whereas the struct in Objective-C is kind 237 238 00:21:31,750 --> 00:21:34,100 of like an insect with just one leg left, 238 239 00:21:34,210 --> 00:21:36,020 it doesn't really do very much. 239 240 00:21:36,020 --> 00:21:43,690 So what you should remember from this lesson is that a struct is a value type and that means that it's 240 241 00:21:43,840 --> 00:21:46,360 copied whenever it's used. 241 242 00:21:46,390 --> 00:21:51,820 So it's equivalent to say if we were working on a presentation together and we've got a template that 242 243 00:21:51,820 --> 00:21:58,810 we're working off, I give you one copy of the template presentation and I have one copy of the template 243 244 00:21:58,810 --> 00:22:03,200 presentation. We work on it alone and independently at home 244 245 00:22:03,250 --> 00:22:11,900 and that means that my edits to that copy will not affect your copy and vice versa. 245 246 00:22:12,010 --> 00:22:18,370 Now, if we were working with classes instead because classes are a reference type, then whenever they're 246 247 00:22:18,370 --> 00:22:25,450 passed around or whenever they're used, say, inside an array or passed as an argument in a function, 247 248 00:22:25,450 --> 00:22:33,280 whenever you try to use a class object, then you're creating a new reference to it. 248 249 00:22:33,430 --> 00:22:39,500 And when you edit it or when you change it, you're always changing the same underlying object. 249 250 00:22:39,580 --> 00:22:46,980 And this is equivalent to us working on a presentation together and we've only got one printed copy. 250 251 00:22:47,170 --> 00:22:54,070 So what that means that if you decide to scribble a mustache over my headshot in the presentation, well, that 251 252 00:22:54,100 --> 00:22:56,000 is what we're going to present at the end. 252 253 00:22:56,080 --> 00:23:02,610 All of your changes affect mine because we're all referencing the same object. 253 254 00:23:02,650 --> 00:23:09,610 So in terms of the differences between structs and classes, structs are simpler, they are faster because they're 254 255 00:23:09,610 --> 00:23:11,940 stored in the stack, rather than the heap, 255 256 00:23:11,980 --> 00:23:15,150 and you can create deep copies of structs 256 257 00:23:15,190 --> 00:23:17,690 that are not just references to an object. 257 258 00:23:17,890 --> 00:23:19,600 They have true immutability. 258 259 00:23:19,600 --> 00:23:26,110 So when you declare a struct as a let, then you can't change any part of the struct including its properties 259 260 00:23:26,110 --> 00:23:27,010 and methods. 260 261 00:23:27,010 --> 00:23:33,670 And finally, you have less memory leaks and thread safety as well which we're going to go into when we 261 262 00:23:33,670 --> 00:23:42,080 explore more topics, such as memory management and multithreading. Now, in comparison, classes, they have inheritance, 262 263 00:23:42,120 --> 00:23:49,500 and this is the biggest thing that's going for them because inheritance is core to object-oriented programming, 263 264 00:23:49,650 --> 00:23:54,840 being able to inherit and subclass is what makes OOP so powerful. 264 265 00:23:55,050 --> 00:24:01,830 So when you need inheritance, then you'll need to use classes. And, also, classes will allow you to work 265 266 00:24:01,830 --> 00:24:03,340 with Objective-C code. 266 267 00:24:03,720 --> 00:24:08,540 And a lot of the API for the iPhone is still in Objective-C. 267 268 00:24:08,580 --> 00:24:13,410 So when you need those components that are written in Objective-C, then you can't interact with them 268 269 00:24:13,440 --> 00:24:14,720 using a struct. 269 270 00:24:14,760 --> 00:24:20,910 So the official Apple advice, which was updated only a few weeks ago, and this is apparently their final 270 271 00:24:20,910 --> 00:24:28,470 word on this topic, is that you should use a struct by default whenever you want to create a new custom 271 272 00:24:28,470 --> 00:24:36,510 object, and only turn it into a class when you find that you actually need inheritance or you actually 272 273 00:24:36,510 --> 00:24:42,060 need to be able to work with Objective-C code. And then, in that case, turn the struct into a class. 273 274 00:24:42,060 --> 00:24:49,950 So in certain cases, you still need to rely on classes, but start with a struct and only go up if needed. 274 275 00:24:49,950 --> 00:24:53,880 This is exactly the same as the advice for Swift access levels. 275 276 00:24:53,880 --> 00:25:02,880 Start with the least inclusive, most private access level, and only increase its capability as and when 276 277 00:25:02,880 --> 00:25:03,570 needed.