Hey, guys. 1
Welcome to another Swift Deep Dive. In this deep dive, 2
We're going to be learning all about Swift Classes, 3
what they are, what they can do, and how to create them. 4
Now, classes like structures are, again, a way of defining a blueprint. They're a way for us to be able to 5
plan our properties and methods. And eventually, when we run our app, be able to initialize our class into 6
an actual object. 7
So in this lesson, I'm going to talk about how to create an object from a class. But in addition, I also 8
want to talk about some of the core concepts of object oriented programming, namely inheritance, subClasses, 9
SuperClasses, 10
what it means to override a method, and what it means to call a method from a SuperClass. 11
So let's create a separate project in Xcode to show these concepts in action. 12
I want you to go to File, New, and choose a New Project. 13
Now, when you see the wizard, I want you to choose macOS and select the Command Line Tool. 14
Now, the reason for this is we're not actually creating an entire app, but we are creating a project which 15
can have multiple swift files associated in the same project. Our project name is going to be called 16
ClassesDemo and then you can go ahead and click Next, and save it anywhere you like. 17
So, this is what you should end up with. 18
And notice how we have a main.swift file that already gets created for us. And inside, all we have 19
is just a print statement. 20
So I want you to delete everything that's currently inside your main.swift. And you'll notice that 21
when we run our project this time, what will happen is it will look inside the main.swift file and 22
run all the lines of code in here as if it were a playground. 23
So if I wrote print "hello," well, then that is what will be run and printed into my debug console 24
when my program runs. So we can expand this and we can collapse the right-hand pane. And in fact, I'm also 25
going to collapse this left-hand pane, 26
so we have a full length debug console. 27
So now it looks pretty similar to what we have when we create a playground. 28
But in this case, I can actually create multiple files inside the same project, 29
my ClassesDemo project. 30
So how do we write the code for our class? Defining a class is very similar to defining a struct. 31
We have the class keyword and then we have the name of the class which is capitalized from the start, 32
and then we have a set of curly braces inside of which we can define the implementation of the class. 33
Let's create a new Swift file for a class in our project. 34
So here I'm going to right-click and I'm going to create a new file in that folder which is going to 35
be a new Swift File, and then hit Next. 36
And now, I'm going to name my file the name of the class 37
that I'm going to create which is going to be called Enemy. 38
So let's imagine that we were building a simple game where we have to create enemy characters for our 39
game. 40
So the first thing I'm gonna do is I'm going to delete all of the code in here. 41
We are going to create our code entirely from scratch. In this enemy.swift file. 42
I'm going to create my Enemy class. To create my class, 43
I'm gonna use the class keyword, and then I provide the name of my class which is going to be called 44
Enemy. And it is convention that when you create a class that the name of the file matches exactly the 45
name of your class. 46
Now, I'm going to open a set of curly braces to define this Enemy class, 47
what it can do, and its properties and its methods. For the Enemy characters in my game, 48
they might have a number of attributes or properties, right? Things like, maybe they would have a health 49
stats, let's say that they start out with 100 health. And they might also have an attack strength, so this 50
is how hard they hit. 51
Now, these are the properties of my Enemy class. But I can also describe behaviors that the enemies can 52
perform. 53
So I would do that by creating a function. 54
Let's say that each of my enemy characters can move, so I could have a move function. And when this move 55
function is triggered, all that happens is that the enemy characters "Walk forwards." 56
Now, we can also define a attack function. And when the enemies attack, what should happen is, maybe they 57
would "Land a hit" and it will do some damage depending on the attack strength of this enemy character. 58
So I'm going to use string interpolation to insert the attack strength value in here. 59
So, for example, a default Enemy character with an attack Strength of 10. When it attacks, it's going to 60
land a hit, and does 10 damage. Now that we've defined our blueprint that defines an Enemy character, it's 61
time to go into our main.Storyboard and we can initialize our Enemy class here and create an object 62
from that class. So to initialize a class, 63
all we do is write the name of the class, and then a set of parentheses. 64
So in our main.swift, I'm going to create a new Enemy. 65
Let's say, it's a little skeleton and I'm going to initialize it as a new Enemy object, 66
so the name of the class and then a set of parentheses. 67
So now that I've got this enemy object which is a skeleton, I can tap into its properties. 68
So, for example, I could print the skeleton.health property. And if I run my app by clicking the 69
play button, 70
you'll see that the skeleton gets created on line two, and on line 3, I'm printing its health which turns 71
out to be 100. And that, of course, comes from the default health property for everything that's created 72
from the Enemy class. 73
Now, in addition to using the properties, I can also get my skeleton to do something, so I can write 74
skeleton.move or skeleton.attack. 75
So now if I run my code, you can see that the health is printed as 100, the skeleton now walks 76
forwards, it lands a hit and does 10 damage. Just by creating this Enemy class, I can now create lots and 77
lots of enemies. I could create more skeletons, so skeleton2 is going to be created again from the Enemy 78
class, and then maybe we could have a skeleton3. and instead of having to create each one of them with 79
a health stat and attack strength, define its behaviors, I've now used that template or that blueprint, 80
the Enemy class, to create three entire skeleton objects which each can move, can attack, have all these properties. 81
So as you can imagine, it's a lot easier to simply replicate and airdrop in all of these different enemies 82
without having to define each of them from scratch. But in the last module, we saw how to use structs 83
or structures. And we could do pretty much the same thing with them, right? 84
But that's not where it ends. 85
The magic of classes really lies within a special capability that they have which is the ability to 86
inherit from a SuperClass. 87
So what do I mean by the SuperClass? 88
And what does it mean to inherit from a SuperClass? 89
Well, the key to understanding this is that we can have a relationship between classes. 90
Think of the SuperClass as a parent. It knows how to do certain things and has certain properties and 91
methods. 92
However, what if we want to take its existing capabilities and build on top of it? 93
Well, yeah, we could do this by adding more code to our existing class. But there's also another way. We 94
can create a SubClass and add our additional functionality there. 95
Think of the SubClass as the child of the SuperClass. The SuperClass is taught the SubClass everything 96
it knows how to do, 97
for example, reading and swimming. And the SubClass can now grow and develop its own capabilities like 98
playing with the iPhone, getting addicted to YouTube, or live streaming on Twitch. 99
In other words, the SubClass has access to all the properties and methods of the SuperClass. 100
That's what we mean by inheritance. 101
Now, let's see inheritance in action in our Xcode project. 102
So let's say that I want to have these generic sort of simple enemies like skeletons. 103
I don't know why skeletons always get a bad rep. They always seem to be the most easy to destroy enemies 104
in any game I've played. 105
But let's say that we wanted to have a more powerful enemy and we wanted to leverage the code that we've 106
created in our Enemy class, 107
but we wanted to make it do more and be more specialized. 108
Let's say that in my ClassesDemo, I create a new file, again, a Swift File, and I name this file Dragon. 109
So I want to create a Dragon class in this file. 110
So I do exactly the same thing as before, but this time I'm going to use the class code snippet that 111
Xcode auto-suggest gives me, and I'm gonna hit enter 112
once I select it. 113
Now, this is the default way that we would create a class, whereas before we created a class that was 114
just a simple standalone class. 115
In this case, I'm going to use the ability of classes to inherit from other classes. 116
Firstly, I'm going to give this class a name which is gonna be my Dragon class and dragons are also a 117
Enemy, 118
so they're going to inherit from the Enemy class. 119
So that means when I create a dragon from the Dragon class, I don't actually have to redefine these properties 120
or these methods. 121
It already has inherited all of those properties methods. And I can show you by simply going into my 122
main.swift and I'm going to delete all of this code here. And this time, I'm going to create a dragon. 123
So the dragon is gonna be created from the Dragon class. 124
And now with my Dragon class being completely empty other than the inheritance from the Enemy class, 125
I'm going to use my dragon object, and I'm going to get it to move and I'm going to get it to attack. 126
So now if I go ahead and delete all of this code and simply go ahead and press run, you can see that 127
when this line 6 runs, the dragon walks forwards, and it also lands a hit when the attack method runs. 128
So without having to lift a finger, essentially, in our Dragon class, we've already managed to inherit 129
all of the capabilities in the Enemy class just by inheriting it like so. Now that's not where it ends though, 130
the whole reason I created this Dragon class is for it to be able to do something different. 131
So let's create a property that is unique to our Dragon class. So maybe it has a wingSpan, and let's set 132
it to default value of 2 meters. 133
So it's a medium-sized dragon. But when I create my dragon object, I could change that. 134
So I could say dragon.wingSpan and let's set it to 5. 135
Let's make it a giant dragon. 136
So this wingSpan property, of course, does not exist in our default sort of Enemy class. 137
I can't say skeleton.wingSpan. 138
That doesn't make any sense. 139
Skeletons don't have wings. 140
So that is a custom property that only exists inside the Dragon class. 141
But, of course, the Dragon class also has access to all the properties that the Enemy class has because 142
it is inheriting from it. 143
So, for example, it has the health property, it has the attackStrength property. 144
So let's set the attackStrength property to a bit higher than your average enemy. 145
Let's make it 15 instead of 10. 146
But in this case, I'm creating a new dragon from the Dragon class and I'm tapping into a property from 147
the SuperClass, so the class that we're inheriting from. Now, I also want my Dragon class to be able to 148
do something that the default Enemy class can't do. 149
Now, it seems to me like from all the movies I've watched, dragons always seem to be able to talk. 150
So let's give our dragon the capability of speech by adding a method code "talk," and this method is 151
going to take a input code "speech", and that's gonna be a string data type, and then all that it's gonna 152
do is just print the words it says whatever the speech happened to be. 153
So I'm just going to insert that speech input in here. And now we've got a dragon that talks. So back 154
in my main.swift. 155
I'm going to say dragon.talk. And the speech that it's going to give is "My teeth are swords! My claws 156
are spears! My wings are a hurricane." 157
So now we've got a dragon that talks, that moves, that attacks. 158
And if I run my code as it is, you can see that my dragon is talking, it's walking for some reason, and 159
it's landing a hit doing a 15-point damage. So you can see we've now got this dragon object created from 160
the Dragon class which can do everything that the enemy can do, but it can do a lot more. 161
So there's some custom things that only the dragon can do that a bog-standard enemy can't. 162
But if you look at our code, when the dragon moves, it probably shouldn't walk. 163
I think it should probably fly instead of walk, 164
right? 165
So in addition to defining custom properties and methods, we can also tap into the methods that are available 166
to us from the SuperClass, 167
so the class that we're inheriting from, and we can override it. 168
So if we tap into the move method, you can see that this override keyword goes in front of our normal 169
function declaration. 170
And this means now that when we trigger the move method, we can say it does something completely different. 171
In my case, 172
I think that when a dragon moves, instead of walking, it probably should "fly forwards." 173
So now if I go back to my main.swift without changing any of this code, I run my code, 174
you can see now when my dragon moves, it flies forwards, instead of walking forwards. And I've managed 175
to achieve that by overriding this method that I got from my SuperClass and providing a custom implementation, 176
so doing something completely different from the move method that the dragon inherited. 177
Now sometimes, however, you actually want the behavior of the method from the SuperClass. 178
So in our case of our dragon, what if I want it to land a hit, do some damage, but also to maybe be 179
able to spit some fire, in addition. 180
Well, in that case, I can do this. 181
I can override the attack method from my SuperClass and I can do something customized to the Dragon 182
class, namely maybe dragons should be able to spits fire and it does 10 damage. But this is not all 183
that I wanted to do, 184
I want it to perform the method that came from the SuperClass, the Enemy class, which I'm inheriting from, 185
but then do some custom stuff as well. 186
So I want both the functionality of the attack method from the SuperClass, as well as some functionality 187
that I've added on as custom. 188
So to achieve this, what I do is I use the super keyword which refers to the Enemy class which I'm inheriting 189
from, 190
and then I write ".attack." 191
So now I'm triggering the attack method from my SuperClass which will print "Land a hit, does X amount 192
of damage," and then I want to "Spits fire and do an extra 10 damage." 193
So now if I go back to my main.swift and I run my code, when dragon.attack gets triggered, my 194
dragon will, first, land a hit, 195
does 15 damage, which comes from super.attack, and then it's going to spit fire and do another 10 damage, 196
which comes from my custom additional implementation of the attack method. So this really is the superpower 197
of classes. 198
You can see that by inheriting from the Enemy class, I saved myself a lot of work and a lot of repetition. 199
When we create functions, we know that they help us reduce the amount of repeated code by packaging a whole 200
bunch of instructions inside the same package. 201
Now, when we create classes and inherit from other classes, we're, again, saving ourselves from creating 202
repeated bits of code, 203
and instead, we are just layering functionality upon a SuperClass. 204
So in fact, without this capability of inheritance that comes from classes, we wouldn't have been able 205
to build any of the apps that we have created so far. 206
If you go to help and develop a documentation, you can see how inheritance is used amongst the components 207
that are part of Apple's UIKit. And that includes almost everything we've shown on screen like 208
UILabels, UISliders, UIImageViews, everything with a UI in front of it, basically. 209
So for example, when we create a button, we're actually creating a UIButton. 210
So if you search for a UIButton and click on it, you can see that this is a UIButton Class and it allows 211
you to respond to user interactions. But this class actually inherits from the UIControl Class, 212
so if we click on UIControl, we get taken to this class' documentation and you can see that this is 213
the base class for all of the controls which convey a specific action or intention in response to user 214
interactions. 215
So we're inheriting some of these capabilities 216
when we use a UIButton. Now, a UIControl itself then inherits from a UIView which is an object that manages 217
the content for a rectangular area on the screen. And then a UIView itself inherits from UIResponder, 218
and UIResponder inherits from NSObject. 219
So what does that mean? 220
Why is it structured like that? 221
Well, let's think about it in reverse. 222
Apple's most basic class is the NSObject. 223
This is the simplest and most generic component 224
and it's how Apple started out. The NS, in fact, stands for NeXTSTEP which was the company that Steve 225
Jobs started when he got kicked out of Apple, initially. 226
Now, the UIResponder can do everything an NS object can do, but it has its own additional capabilities. 227
The UIView in turn builds on top of the capabilities of the UIResponder, and the UIControl builds 228
on top of that again. At each level. 229
more code and more capabilities are added so that components become less generic and more specialized. 230
Until finally, we get a UIButton that the user can press. So now that we've chased it all the way up 231
the tree, 232
we can see how it would take so much longer if we had to create everything from scratch, and create all 233
of our view controllers from scratch, all of our UILabels from scratch, rather than simply just inheriting 234
and using the capabilities that Apple has already created within our UIKit. 235
And this is all possible because of how classes work and how they're able to inherit from other classes. 236
So in the next lesson, we're going to take a look at the difference between struct and classes and when 237
we would use each. 238
So for all of that and more, I'll see you there.