Bummer! This is just a preview. You need to be signed in with a Basic account to view the entire video.
Start a free Basic trial
to watch this video
If you haven't been amazed by extensions yet, you definitely will be. In this video, we look at how we can extend protocols themselves to provide default implementations.
-
0:00
We just learned how to extend any type to conform to a protocol.
-
0:04
Just like we can extend a class struct or a number.
-
0:07
But things get a little interesting when you do that.
-
0:10
Unlike other types where when we extend it we can add functionality.
-
0:14
When you extend a protocol you can provide implementations to any method or
-
0:19
property requirements that you have defined.
-
0:22
Wait, what?
-
0:23
When we learned about protocols we said that the purpose of a protocol
-
0:27
is to just define requirements and not worry about the implementation, right?
-
0:33
That was the job of the conforming type.
-
0:36
And that still holds true.
-
0:38
However there are certain cases where regardless of the conforming type,
-
0:42
the implementation remains the same.
-
0:45
Let's look at this simple example first.
-
0:47
Now in the past we've defined a protocol called Random Number Generator.
-
0:52
The only requirement was that conforming types
-
0:55
needed to provide a function that returned a random number.
-
0:59
So we'll add that in here.
-
1:00
First let's add a comment or same protocol extensions.
-
1:06
And then let's define this protocol.
-
1:08
So it was called RandomNumberGenerator
-
1:13
at a single method requirement a function random.
-
1:18
That returned a random integer.
-
1:21
Now let's assume that for every type that conforms to this protocol,
-
1:26
the implementation will always be the same.
-
1:28
We're going to use the arc for random function to generate a random number.
-
1:32
In such cases, where we will have a common implementation and
-
1:36
an occasional variation.
-
1:38
We can provide that common implementation as part of the protocol itself
-
1:43
via an extension.
-
1:45
So let's create an extension to the protocol itself and
-
1:49
even here inside this extension we're going to provide an implementation or
-
1:54
this function that we've defined as a requirement in the original protocol.
-
1:58
So, we'll say func random.
-
2:04
And we're providing an implementation which means just writing out
-
2:08
a normal function.
-
2:09
Then here, we'll say return, Int arc4random and there we go.
-
2:16
Now, if I were to declare a new type let's say a class called generator
-
2:25
and then conform to the random number generator protocol.
-
2:29
You'll see that I can add conformance to this type without actually doing anything.
-
2:35
This error should go away in a second.
-
2:37
And generator now conforms to random number generator, but
-
2:40
I don't have to provide a random function.
-
2:44
This is because a default implementation has been provided in the protocol and
-
2:48
the conforming type generator can use that.
-
2:51
For instance if I say let generator equal and I'll create an instance of generator.
-
2:57
On this I can call random and it should work.
-
3:02
So here the generator type is relying on that default
-
3:06
implementation provided by the protocol itself.
-
3:09
Again which we can do through an extension of the protocol.
-
3:13
If however we decide that we don't want this
-
3:16
default implementation that the protocol provides and
-
3:18
we want the type to provide its own specific implementation.
-
3:23
Well that looks just like before like we've been conforming to a protocol.
-
3:26
We can provide our own implementation.
-
3:29
So in here I'll say func random and I'll just return something
-
3:35
like 2 to make it obvious that it's different and you'll see now it returns 2.
-
3:39
Interesting, right?
-
3:41
Well depends on your definition of interesting I suppose.
-
3:44
Okay, well let's look at another example.
-
3:47
This one requires a bit of a deeper understanding of protocols.
-
3:51
Let's define a new protocol, person.
-
3:55
And it's going to have a first name string property that's gettable.
-
4:01
A last name also string gettable and
-
4:05
a full name, also a string, also gettable.
-
4:10
The requirements here are pretty simple.
-
4:12
Conforming types need to provide a first, last and a full name but
-
4:16
we know that a full name is always going to be the first name and the last name.
-
4:20
So let's provide a default implementation for that property.
-
4:25
So extension.
-
4:26
Remember we can only provide default implementations for
-
4:29
protocol through an extension.
-
4:31
So extension person save our full name.
-
4:35
I'll type string and we'll return in here an interpellated string.
-
4:41
Wait, what do we do here?
-
4:43
We can't anticipate everyone's full name, so what kind of string do we return?
-
4:48
Can we anticipate all the possible names?
-
4:50
Well, we don't need to.
-
4:52
Since we're in an extension of the person type,
-
4:56
we know all the information that's available to the person type.
-
5:00
Which means we know about the first name and the last name stored properties.
-
5:04
Now what do I mean by know about it?
-
5:07
The person protocol has requirements stating that conforming types
-
5:11
must provide a value for firstName and a lastName.
-
5:15
The types for these properties are non optional strings.
-
5:19
Meaning they cannot be nil.
-
5:21
Therefore we can guarantee, or the compiler can,
-
5:24
that conforming types will have values for the first and last name.
-
5:29
And since the conforming types are the ones that are going to be calling this
-
5:33
full name property as well, we can use the values encapsulated
-
5:37
by these properties in the eventual conforming type.
-
5:41
So right now they don't have any values but we can use them,
-
5:45
we'll say return firstName and lastName.
-
5:50
And this should work because eventually when a conforming type
-
5:53
conforms to the person protocol they will provide values for first and last name.
-
5:58
Let's see if this works by defining a new type.
-
6:02
This is a struct called User, that conforms to Person.
-
6:10
It needs a first name.
-
6:11
Let's get rid of that.
-
6:13
And a last name and let's change that to let as well.
-
6:19
Notice that I'm only providing the implementations in the form of stored
-
6:23
properties for the first and last name but we don't have any errors and that's
-
6:27
because again a default implementation for full name has been provided.
-
6:32
So if we were to create an instance,
-
6:35
we'll say let user = User and put my name in there.
-
6:42
I can now call full name on user and
-
6:44
you'll see that the correct string is returned.
-
6:48
Despite user not having an implementation.
-
6:52
When we call the method we use the implementation in the protocol extension
-
6:56
where it relies on the values provided by user for
-
6:59
some of the other requirements specified in the protocol.
-
7:02
There's a hidden aspect to this though.
-
7:04
Let's take a break and talk about method dispatch in the next video.
You need to sign up for Treehouse in order to download course files.
Sign up