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.
