Hey, guys. 1
Welcome to the Swift 2
Deep Dive on protocols. In this deep dive, 3
Wwe're going to be talking about what Swift protocols are and what they allow us to do. 4
So the way I like to think about protocols is imagine it as a certification that you have in your CV 5
or your resume. 6
So for example, in my LinkedIn profile, I've got a bunch of certificates that I've listed. And one of those 7
certificates is something called Advanced Life Support. 8
So this is something that every doctor in the UK has to complete and it's a two-day course where we 9
learn a whole bunch of things, including how to deliver CPR to resuscitate people who might have had 10
a cardiac arrest. 11
Similarly in Swift, we can create these protocols or certifications if you will that have a bunch of 12
requirements. And when our classes or our structs adopt this protocol, it means that they are able to 13
meet these requirements and have these skills. For example, performing CPR or resuscitating somebody who's 14
unconscious. 15
So the way that we define our protocol starts with the protocol keyword. 16
And then we give it a name. And similar to structure and classes, 17
it's also named starting with a capital letter. And then in between a set of curly braces, we can define 18
the requirements of this protocol. 19
So let's take a look at this in more detail. 20
I'm gonna head over to Xcode and create a new project and I'm gonna select the macOS command line 21
tool to be able to allow us to see multiple files. 22
I'm gonna call this product name Protocols Demo and then go ahead and hit next. And then you can save 23
it wherever you want. 24
Now, inside my Main.swift, I'm actually going to delete everything that's in there because we don't need 25
any of it to write the code. Protocols is a fundamental aspect of Swift and it doesn't rely upon anything 26
else. 27
Now, let's write some code to see what problems protocols can solve. 28
The first thing I'm gonna do is I'm going to create a new class and my class is going to be a Bird class 29
and I'm going to define a bunch of things that birds can do. 30
So for example, birds can usually fly. 31
And so I've got a fly method in my Bird class. 32
And when my bird flies, all that it does is it flaps its wings and it lifts off into the sky. 33
So I'm going to create a very simple print statement to represent this functionality of a bird. 34
Now, in addition, if a bird is female, then they can also lay eggs, right? 35
So let's create this layEgg functionality where we check to make sure. If our bird is female, then in 36
that case, we can go ahead and print "The bird makes a new bird in a shell." 37
So here we've got our Bird class created. And based on what we learned in our classes Deep Dive, we know 38
that we can inherit from different classes. 39
So if I created another class, let's say, I create a Eagle class and it's going to be inheriting from 40
the Bird class. 41
So now I've got this Eagle subclass which inherits from my Bird class. The Eagle now gets access to everything 42
a bird can do. 43
So, for example, let's create our own Eagle. Let's call it myEagle and it's going to be a new Eagle object 44
created from the Eagle class blueprint. 45
And then I could say, well, myEagle, you can fly, myEagle if it's female, it can lay eggs, and we've set 46
everything by default as female. So our eagle is able to fly and lay eggs. Pretty simple so far. 47
Now, in our Eagle class, let's say that our Eagles are able to do something a little bit more specialized 48
that maybe not all birds can do. 49
Maybe it can also soar. So our Eagle is able to take advantage of the air currents. And using the warm air, 50
it's able to glide through the air using these air currents and not all birds are able to lock their 51
wings and do this apparently. 52
Now, our Eagle is also in addition to everything it got from the bird class that it inherited, 53
it's also able to soar. 54
So now we've created are Bird class, we're able to inherit from our Bird class, and that's all just a 55
review so far. At this point, you might be wondering, "Well, where's the problem here?" 56
This is a really good time to use inheritance, 57
right? 58
Well, let's say that a couple months down the line, we create another class, myPenguin class which is 59
also going to inherit from the Bird class. 60
Penguins are indeed birds. 61
They have wings and they have feathers. And penguins, in addition, can also swim. 62
So my penguin is able to paddle through the water. 63
So let's say that we create an object from our Penguin class. We'll call it myPenguin. 64
And this is, of course, created from the Penguin class and we initialize it 65
And now my penguin is able to lay eggs. 66
It's able to swim. But curiously, it's also able to fly. It inherited that method because it's a bird. 67
But as you may already know, penguins can't actually fly. 68
Their wings are far too small to be able to support themselves in air. Now, we have a bit of a problem, 69
right? 70
We want to be able to define the penguin as a subtype of birds, but we don't really want it to inherit 71
the fly method. 72
So this is the first problem we run into our Penguin is inheriting some functionality that it shouldn't 73
have, 74
And this can lead to unintended consequences like a flying Penguin. Let's say that we had a flying museum, 75
right? Let's call it FlyingMuseum and let's create as a structure because we don't need to inherit anything, 76
we don't need any of the class features. 77
So let's say that we have our flying museum which puts on these flying demos every so often. And in these 78
demos, it takes a flying object. 79
So it has to be able to fly to be able to do this demo. 80
So the flying object, we're going to say it's of type bird, because we know that all birds can fly. 81
They have this function fly in their class definition. 82
So now when our flyingMuseum puts on the flyingDemo, well, all it does is it collects all of these things 83
that can fly, 84
and it gets the flying object to fly. 85
So now let's create our museum, which is a flying museum, and our museum puts on a show, a flyingDemo. 86
So let's huddle up all of our birds that we have access to in our museum and let's get myEagle to be passed 87
in as the input to the flyingDemo. 88
So now if I run this code as it is, you can see that once it's done running, I get the bird flaps its 89
wings and lifts off into the sky. 90
So the only reason why I'm able to do this is because I was able to pass myEagle, which is an eagle 91
type, into the flyingDemo as a flyingObject because the Eagle class inherits from the bird Class, and 92
therefore, it's also a bird type which, therefore, satisfies the data type of this input. 93
So it's able to be used in my flyingDemo. 94
Now, similarly, if I create my penguin and I pass in myPenguin, 95
and when I run my code, we get a flying penguin and a very surprised audience at the museum's flying 96
demo. 97
This is the kind of unintended behavior I was talking about. The entire code base assumes that all birds 98
can fly, but we have one bird that clearly shouldn't be flying. 99
So the problem is that we're relying too heavily on inheritance and subclassing. Say, your app has become 100
a huge hit and now you want to have flying behavior in other parts of your code, 101
well, birds shouldn't be the only thing your museum is showing off in the flying demo, right? 102
So how would you get that to work? 103
Let's say that I had a structure that's an airplane. And my airplane, 104
well, I also want to say that, well, airplanes can fly, right? 105
So at the moment, the only things that can fly are birds. 106
That's the one that has the fly method implemented. 107
And if I want to be able to use my airplane in my flying demo, well, then it kind of has to be a bird 108
type because that's the only thing that I can put in here. 109
If I just had an airplane struct that I created down here, let myPlane equals Airplane, and I tried to 110
pass in myPlane in here as the input, 111
well, then I'm going to get an error because this has a type of airplane which is not in any way related 112
to type bird which is what I'm making a requirement as the input type. 113
So what can we do? 114
Well, we could force our code to work by making our airplane a type of bird. But now we have a problem 115
because structures cannot inherit. 116
So let's go ahead and fudge our code a little bit more and turn our airplane into a class to make it 117
inherit from bird. 118
So now that works, but let's see what happens when we put our plane into the flyingDemo. 119
It says that the bird flaps its wings and lifts off into the sky. 120
But, actually, wait a minute. 121
It's a--it's an airplane. 122
What's going on here? 123
Well, it's because the plane inherits from bird which has the implementation of fly and fly says that 124
the bird flaps its wings and lifts off into the sky which is fair enough for birds. 125
But it's very weird for an airplane to flap its wings. 126
So while we could, let's say, override our methods fly. And, you know, for airplanes we could print, instead, 127
that the airplane uses its engine to lift off into the air. 128
And now, I've kind of forced my code to work because this is now what we're getting in our flyingDemo. 129
But there are headaches with this way of doing things. 130
For example, my plane is now able to lay eggs which makes absolutely zero sense, whatsoever. 131
So how can we solve this problem? 132
How can we separate the flying behavior from the bird class? 133
How can we have both classes and structures that can fly? 134
Remember that inheritance only works for classes. 135
So maybe we shouldn't be using inheritance to get hold of the flying functionality at all. 136
And this is where protocols come to the rescue. 137
So let me just clear up my code a little bit to make it easier to see what's going on. 138
And right at the top, I'm going to declare a protocol. The name of my protocol is going to be called 139
CanFly. 140
And this is, basically, like the certificate that I mentioned before. 141
So everybody that can fly, 142
they've gone to the flying training. 143
They have this capability of flying. But in order for you to be someone that can fly or something that 144
can fly, 145
well, we have some requirements. 146
You must be able to implement a fly method. 147
Now, notice how this fly method that goes into the protocol doesn't actually have an implementation. 148
It doesn't have a set of curly braces which defines how it should be flying. 149
And in fact, if you try to do this, Xcode will give you a warning saying, "Protocol methods must not have 150
bodies." 151
So it only has this part. It can't have any curly braces and any implementation. Now, that we've created 152
this can fly certificate with a fly method that must be implemented by everyone who says that they can 153
fly, 154
we can now go ahead and delete our fly method from our Bird class because not all birds can fly. 155
And instead, we can say that our birds which can fly, our Eagle class, for example, well, they're going to 156
adopt the CanFly protocol. And as soon as we do this, we get a error from Xcode telling us that you 157
said that eagles can fly, but you haven't actually implemented a fly method in here. 158
So if we click on this and we say, "Fix," well then it's going to add the fly method that is required by 159
this CanFly protocol. 160
And in here, I'm going to add a print statement that says, "The eagle flaps its wings and lifts off into 161
the sky." 162
So my eagle can fly because it implements the fly method, 163
so it satisfies the requirements of my protocol. 164
So the Eagle now has this protocol or this certification. And my penguin is not going to get this 165
CanFly certification. 166
It's just a bird. 167
It has feathers, it has wings, it can swim, 168
it can lay eggs, but it can't fly. 169
But my airplane, on the other hand, now no longer has to be a class. 170
It can be a struct because we actually don't need to inherit anything. 171
Instead, it's also going to adopt the CanFly protocol. 172
So protocols can be adopted by structures or classes. 173
It's not like inheritance, it's not limited to classes. 174
So now my airplane has this CanFly protocol, so it must implement the required method which is flying. 175
If you say that you can fly, 176
you must have an implementation. 177
So "The airplane uses it engine to lift off into the air." 178
And now in my flyingMuseum, rather than limiting my flyingDemo to using flying objects that are birds, 179
I'm going to use a different data type. 180
I'm going to use the CanFly protocol as a data type 181
So now I'm saying that when my flyingMuseum puts on a flyingDemo, it requires a flying object 182
that is something that adopts this protocol, because I know that when they adopt this protocol, they definitely 183
have a fly method implemented. 184
So I'm pretty sure that I'm not going to embarrass my museum by trying to demo a object that can't fly. 185
Now, down here, my plane can no longer lay eggs because it's now just a simple structure that is an airplane, 186
but it does adopt the CanFly method. 187
Now, myEagle is able to fly. myPenguin is not able to fly, but it can do all of the other things that 188
birds can do because it's still inheriting from the Bird class. 189
But my airplane is now able to fly. And more importantly, when I put on my flyingDemo at myMuseum, I 190
can now pass in myEagle which is able to go in here because it adopts the CanFly protocol. 191
I can also pass in myPlane because it also adopts the CanFly protocol, but I can't pass in myPenguin 192
because it does not adopt the CanFly protocol. 193
So now instead of using inheritance where I'm saying my eagle inherits from the Bird class and my penguins 194
inherit from the Bird class, and if birds are able to fly, then all the subclasses of birds, eagles and 195
penguins all get this capability which it may or may not actually need. 196
But on the other hand, when my airplanes actually need this CanFly ability, it can't really inherit 197
from birds because it doesn't satisfy the other things that birds can do like laying eggs. 198
Now, because we've learned about protocols, we can make our code much better. 199
We can simply adopt that CanFly protocol everywhere where we need that capability. 200
So our airplanes become a type that can fly, our eagles also become a type that can fly, 201
and it means that we're assured that when we use an eagle or when we use an airplane, because it's marked 202
as CanFly, it will definitely have a fly method implemented. 203
This is our protocol in action. And as we mentioned, structures can adopt protocols, 204
classes can adopt protocols, but you can also adopt multiple protocols. All you have to do is after the 205
name of your structure or your class, 206
you add a set of colons and you add your protocols one after the other 207
separated by commas. 208
Now, if you are creating a class and it needed to be able to inherit from a superclass, 209
well, in this case, you're Superclass comes first. 210
So it's going to be the name of the class, colon, the name of the Superclass, and then the protocols come 211
after the Superclass separated, again, by commas. If you'd like to know more about protocols and how they 212
work in detail, 213
I recommend browsing through the Swift Language Guide on protocols. 214
As always, you'll find a link in the course resources. 215
But let's get back to our app. So now that we've seen what protocols are, we can see that all 216
UITextField delegate is in fact just a protocol with a whole bunch of requirements. And those requirements 217
are methods for implementing the textFieldShouldBeginEditing, the textFieldShouldEndediting, et cetera, 218
and all of these things. 219
But why is it a delegate? And how is it able to trigger all of these delegates? And what does it mean 220
when we said the search field's delegate as this current class? 221
Well, we'll explore all of that by doing another Deep Dive in the next lesson 222
where we look at the delegate pattern using Swift protocols. So for all of that and more, I'll see you on the 223
next lesson.