Intermediate Swift

Initializers

Your browser needs to be JavaScript capable to view this video

Try reloading this page, or reviewing your browser settings

Autoplay:
View previous videoPrevious video

Construct an initial object by injecting structs or classes with initializers.

Keyword

  • struct class swift initializer convenience designated

About this video

Author(s)
Lucas Derraugh
First online
29 August 2020
DOI
https://doi.org/10.1007/978-1-4842-6410-2_8
Online ISBN
978-1-4842-6410-2
Publisher
Apress
Copyright information
© Lucas Derraugh 2020

Related content

Video Transcript

Welcome to the segment on initializers. Initializers are used to set up our structure classes with initial values that we pass into the type for construction. Class initializers are a little bit more complicated in that they also have to construct any of the super classes. So they have to follow the chain of self to super, meaning that we initialize our self first, and then, anything that we inherit from, we then have to initialize it, as well. So we have to initialize everything along that chain.

So, in this example, we have a struct called shoe. And, by default, structs will automatically create what’s known as a member wise initializer for us. So if I go ahead and construct a shoe, we will automatically have this member wise initializer that allows us to initialize all of the stated members on the struct. So we can go ahead and say our shoe. And the size, we’ll put in like so. And now we would have a shoe with those initialized values.

So structs are a pretty simple case. If I wanted to create my own initializers for the shoe, though, I can do that by using the initializer syntax, or you say, INIT. And the INITs are quite simple. They just start with the INIT keyword, and then, whatever parameters we want to use.

Let’s say, for example, I only wanted to create the brand. And, instead of passing in the size, the only size I create for these shoe brands are going to be a size 10. Obviously, that’s kind of weird, but you get the idea, is that we can initialize our properties without having to actually pass in values.

So, here, I’m also needing to initialize all the properties. So I also need to initialize the brand, as well, like that. And just to maintain order here, we’ll do it like this. So here we go. We’ve initialized our brand property with the brand that’s being passed in. And then, we’ll initialize our size property with a value of 10.

Now once I’ve done this, we can no longer use the member wise initializer. The member wise initializer only stays around while we have not implemented any initializers. Once we implement our own initializers, then we have to use the ones that we’ve declared.

And so, here, we’ll use the initializer that we just made, like so. And we can make as many initializers on this as we might want. Structs are a pretty simple way. The only rule is that we must initialize all the stored properties by the end of the initialization. That’s it.

Now, classes are a much more difficult case. So let’s go ahead and create a product. And the product is going to have a name and a string. And we’re going to create an initializer for this, which is going to construct the string.

Now, classes do not get member wise initializers. So, unlike structs, we will not automatically have a way to construct this product. We need to create an initializer in order to create this product with a stored property that’s doesn’t have an initial value.

So, here, we’ll make a product. And the product, we will construct with our product. Perfect. So, pretty straightforward case. The only real difference here with the single class case versus the struct case is that we have to define our own initializers. We are not given a member wise initializer to use.

The tricky case with classes comes in once you’ve subclassed a class. So, let’s say, for example, I have a bottle class and that’s going to be a subclass of product. Now, if there’s no properties, it’s easy. You still have the same initializers that you had from the product case. So nothing is different there. The difficult case comes when you’ve created a new property.

So in this case, we’re going to go ahead and create a bottle. And this is going to be represented– the sizes are going to represent how much the bottle can hold. In this case, it’s going to be represented in milliliters.

Now, we’re going to go ahead and construct the initializer for this. And I don’t want to do this one. I want to create my own initializer that’s going to pass in name and it’s going to pass in a size. And what I’m going to do here is go ahead and construct the size using the parameter that I pass in.

But what I’m going to do now is I’m going to rely on the designated initializer, which in this case, is the only initializer the product has, to construct itself. So we’re going to construct this using super.INIT and we’ll pass in the name that we are using in this initializer. And that will initialize everything in product, right? Because products initializers have to initialize everything in it. And so when we’re doing that, we initialize everything that we have in our type first. And then we call super afterwards. You can’t reverse this order. Your entire type has to be initialized before calling super.

All right. So once we have that, let’s go ahead, actually, and demo this. So we have a bottle. You can construct that. We have to use our initializer here. So let’s call it water. And let’s say it holds 1,000 milliliters. And there we go. We have our bottle that contains the following.

OK. So, with that, we have our bottle. But what if we wanted to make a different initializer that, maybe, only takes– let’s just say it only takes a name. And we are going to construct the size of the bottle just as a fixed size. So this is going to be a fixed size of– I don’t know, let’s say 500 or something like that. OK? And we wanted to do super.INIT name, and we wanted to pass in our name.

Now, this might– looks like it should work. But the problem is, of course, that this name is identical to the one in product, right? We can’t just use the same method to do this. And so what we’re going to do here is we’re going to override this, and just like we would with methods. So if the method was declared on the superclass, we’d have to use the override keyword. Same goes for initializers.

So this is a perfectly valid initializer. We have this as a designated initializer, because that’s what this one was already. And we’re just constructing everything on our self and then calling super.INIT.

Now, if there is a case, though, that you don’t want to end up calling the designated initializer, you don’t want to make this a designated initializer. WE could make this a convenience initializer. And the way to do this is we call into self as our initializer. So we’re going to use self, and we’re going to pass in size as the parameter. So what this is utilizing is, it’s utilizing the fact that we already have this designated initializer here that takes all the possible parameters that we want. And generally, that should be your designated initializer, is the thing that can construct the most out of your item. So it has all the properties able to be constructed.

And if we are changing this, the rules for designating initializer is that they can’t call into other designated initializers. And to fix that, we can make this a convenience initializer. So convenience initializers cannot be called by other designated initializers.

So for example, if I subclasses, I could not call into this convenience initializer. I always have to call into the designated initializer. In this case, but that’s fine, because it already has all the parameters. But the convenience initializer, what’s nice about it is, that it can call into other initializers on our self.

And so we’re going to just pass in a size here that’s defined by us. And let’s go ahead and we’ll change this declaration here. And let’s say it was actually 500 milliliters. And there we go. We now have our bottle that we can use as our initializer. We can use either one of these initializers, but this convenient one is just what it sounds like. It may be convenient to use.