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