From the course: Swift 6 Essential Training
Basic Swift classes - Swift Tutorial
From the course: Swift 6 Essential Training
Basic Swift classes
- [Narrator] Even though Swift has an entire library of built-in classes and structs, it's important to know how to create your own. For the next few videos we're going to explore the class and struct syntax, how to add properties, methods, initializers, and finally, how to subclass. Let's start off by defining a class called Adventurer. All we need to do for that is use the class keyword, give it a name, and an open-close pair of curly braces. Any properties and methods defined inside this class declaration are going to belong to specific instances of an adventurer that we create. If you're coming from a language that refers to instances as objects or class objects, that's perfectly fine. Just be aware that we're talking about the same idea. All our adventurers should have a name. So we'll declare a variable called name of type string. They should also have a constant maxHealth of type int. And I'm also going to give them an optional value called specialMove. This is going to be an optional string. Any instance properties like these can be declared with or without initial values based on the situation, it's up to you. They follow the same rules inside classes that we've already seen in previous examples. Now, in order to actually create an instance of our adventurer, we need what's called an initializer function. The purpose of this is to set all non-optional values when an adventurer instance is created. So for this, we use the init keyword and if we hit Enter, auto-complete is going to give us the basic setup. Now initializers are functions so we declare the parameters we want to accept, and these need to match our non-optional values. So we need a string and we need an int, and we'll call the int maxHP. Now inside the init function, the only job this should have is to set our adventurer properties. So we'll say self.name is going to equal the init name parameter, and self.maxHealth is going to be equal to the maxHP passed in. This initializer function is commonly referred to as the designated init, but in many cases you'll need more flexibility, which is where convenience initializers come in. These are essentially overloaded init functions with their own unique signatures. You can have as many as you want, but they do all need to delegate to the designated init at some point in their execution. That sounds more difficult than it really is so let's see that in practice. We're going to declare a convenience init with the convenience keyword, followed by init, and the parameters we want to take in. For this one, we want an option that only requires a name for us to create an adventurer. Our job inside the convenience init is to pass up the name parameter into the designated initializer. And we can do this by using the self keyword, which is going to reference the adventurer class. We'll say self init. And for name, we'll pass it name. And for maxHP, we're going to say these adventurers always start with 100. If we go outside our class curly braces, we can declare instances of our adventurers. So I'm going to say var player1 is equal to Adventurer. I'm going to use our designated init first. I'm going to say Harrison, maxHP is 99. I'm also going to declare player2 and use our convenience init so we can see how this works. And all we need here is a name. Now, if you expand the adventurer, quick lookup in the inspector, you can see that player1 is Harrison 99 and has no special move, so it's nil. Steven is Steven, 100, and also nil for the special move. Since classes can have their own functions, let's add one into adventurer. That's just going to print out our property so it makes a little easier to debug. We're going to say funk printStats with no parameters and no return type. We're just going to use the print function here to debug an interpolated string. So I'm going to say Character is going to be self.name. Max health is going to be self.maxHealth. And we can say player1.printStats and player2.printStats. Perfect. And to really drive home how reference types work, let's declare one last player variable. We're going to call this defaultPlayer, and we're going to assign it to player1. I'm actually going to cut and copy the defaultPlayer, put it up before our printStats so we can see this change. Since both adventurer instances are classes, classes are reference types, if we change a property in defaultPlayer or player1, both of the instances are going to reflect that change. So let's say defaultPlayer.name equals Bob the Noob. You'll see in the debug log that our first character, which is player1 is now Bob the Noob with a max health of 99. The Harrison string was overridden. We can also change player1.name. We can change it back and this will affect both the defaultPlayer and player1 instances. Be careful with this behavior when deciding to store a reference instead of a value type as it can lead to unintended data changes throughout your entire app.
Practice while you learn with exercise files
Download the files the instructor uses to teach the course. Follow along and learn by watching, listening and practicing.
Contents
-
-
-
-
-
-
-
-
(Locked)
Populating the game world26s
-
(Locked)
Value vs. reference types2m 43s
-
Basic Swift classes6m 24s
-
(Locked)
Access modifiers and properties7m 29s
-
(Locked)
Subclassing in Swift4m 21s
-
(Locked)
Basic Swift structs6m 9s
-
(Locked)
Chaining optionals6m 33s
-
(Locked)
Challenge: Inventory system34s
-
(Locked)
Solution: Inventory system5m 13s
-
(Locked)
-
-