If a class is the right way to go for a specific object or group functionality, you need to know how this looks in Swift. In this video, create an example user class to illustrate the different property declarations and methods you can put into a Swift cl
- [Instructor] Let's start our discussion of classes and structures. I'm going to open up the AdventureSwift_Working folder and open the Chapter Seven Playground. Now, classes and structs are going to be the foundational building blocks of any application you write. You can add properties, methods, and initializers to any class, and you can even create subclasses of any existing class. Some programming languages refer to instances of classes as objects, but since Swift classes and structs are so close in functionality, we're just going to be calling any kind of class or struct we create an instance of it.
So let's define a new class here called Adventurer. We're going to use the class keyword, followed by the name of our class, and open and close curly braces. And that's it, now we have a class. So let's add some instance properties. Now, instance properties are variables that belong to a specific instance of a given class. So for instance, if we have multiple adventurers, each instance property will only refer to the adventurer they belong to, not to everybody.
So let's give it a name property of type string, an hp property of type int, and a constant called maxHealth type int with an initial value of 100. Now instance properties don't have to have initial values, but you can assign them if you want, and we're going to get an error here. Class Adventurer has no initializers, and that's exactly correct. We need to make sure that all our non-optional values in a class are set when we create an instance of a class.
So you can't just have uninitialized properties. So let's just clear this up, and I'm going to add a comment, and we're going to use a new keyword here called init, short for initializer. Now this is a function, so it's going to take in parameters. And the parameters are our instance properties. So I'm going to have name of type String, hp of type Int, and for now that's all, because maxHealth we don't actually want to change since it's a constant.
Now the point of our initializer is to assign initial values to our properties, so when we create a new adventurer, we're going to feed in a name and an HP value. Now what we actually need to do in the init function is assign whatever we're passing in to our instance properties. So we're going to use a new keyword here called Self. Now, I'll explain this in a second, let's just write this out. Self.name = name, and self.hp = hp.
The Self keyword here is used to refer to a class's property. It's common in an initializer to name the init parameters the same as your instance properties, so this kind of forms a nice syntax here, but it can be a bit confusing. So what we're saying here is that every time we initialize an adventurer, we're going to pass in a name and an HP, and those values are then going to be set as the properties of the adventurer.
So we'll see that in action in just a minute. Let's go over a few more adventurer properties. We can also have optionals. Here I'm just going to say adventurers have a property called specialMove which is a string optional. And because it's an optional, we don't have to include it in our init function. Now on the other hand of instance properties, a class can have what are called type properties. Now, these belong to adventurers across the board, not just to a single instance.
We use a new keyword here called static to denote a type property, and then we can just declare a variable just like we always have. So I'm going to have our static property called credo, it's just going to be a string. Let's come back to our initializer. The main initializer is called a designated initializer. However, for more flexibility, you could have what are called convenience initializers and you can have as many of these as you like, as long as they end up delegating to the designated initializer at some point.
So let's see this in action. We're going to use the new keyword called convenience, init, and for our convenience init we're only going to require that we have a name. Now, here's the cool part. We can call self init, and we can feed in our convenience initializer property name to our original designated initializer. And I'm just going to set the HP to 100 as a default value.
So this comes in handy when you don't need to specify every property for a class. So for instance, if I want to create all my adventurers with a starting HP of 100, I would use this convenience init and just feed in a name. This is going to cut down on code a lot. Lastly, a class can have computed properties, which come in two variations: read only, and read-write. So they're exactly like they sound. They are properties, but you can add computation logic into them.
So this is a slightly different syntax. We're going to declare a new variable, and this is going to be toFullHP of type Int. Now instead of an equals, we're going to go directly into open and close curly braces, sort of like a function. Now, since this is read only, we're only going to return some computed value. So I'm going to say maxHealth minus hp. Now every time we access toFullHP, we'll get the computed value of max health minus hp.
And we call this read only, because we can't actually set toFullHP to any value, it's only going to return something. If we want to have a read-write computed property, we use what's called a getter and a setter. I'm going to call this var health. It's also going to be an Int. We use the open and close curly braces, and we get a new keyword called Get. Now this is exactly the same as the read only property, we're just going to return some value.
So I'm going to return our HP. And for setting, I'm going to say whatever we choose to pass into health is going to set our HP value to that. This new keyword here, newValue, is defined by Swift to capture the value we're trying to assign to the computed property. So we don't have to worry about handling that ourselves. So now that we've done a lot of work in our class, let's actually take it out for a spin.
I'm going to create a new player variable, and this is going to be of type Adventurer, and to call our init function, we just have an open and closed parentheses. And here you can see that we have both our intializers, our designated one and our convenience one. So I'm going to use our designated first. I'm going to say Harrison, and I'm going to have a starting HP of 95. I'm also going to use our convenience initializer just to show you what that looks like.
With this, we only have to pass in a name and we still get a valid adventurer instance. So let's play around. NewPlayer.health, let's query that. And there we go, we get 95, which is the value of our HP. Now if we try and change newPlayer.health to let's say, 100, we can. And let's query it again, and we should get 100, and if we query newPlayer.hp, it should also be 100.
Perfect. Now just for fun, let's try our toFullHP property, 'cause it's a read only, and we should get zero 'cause we're at full health. Let's say we change our health to 85. Our toFullHP will be computed at 15, which is correct. Don't get overwhelmed here by the complexity of classes. We'll go over a lot more in the following videos.
- Starting new playgrounds and projects
- Variables and constants
- Writing single and multiline comments
- Core string methods
- Working with numbers
- Working with collections
- Creating arrays
- Working with sets
- Application control flow
- Writing functions
- Basic Swift classes and structs