Swift Classes — Part I

Well, well, well. It seems that the time has come to talk about classes in Swift. I’ll admit, I got a little bit scared when I saw the word “Classes” in the Swift Fundamentals book. Not for nothing, but in the past, classes were the nail in the proverbial coffin for me. I didn’t quite understand JS or C# classes, but luckily for me, Swift classes are very easy to comprehend and put to good use.

Classes and structures are very similar, but classes have additional capabilities that are as follows:

  • Inheritance — which enable one class to inherit the characteristics of another
  • Reference counting — allows more than one reference to a class instance
  • Deinitializers — enable an instance of a class to free up any resource it has assigned
  • Type casting — enables the user to check and interpret the type of a class instance at runtime

So when should we use structures and we should we use classes? The Swift Fundamentals book informs us that as a basic rule, we should start new types as structures until we need one of the features that classes provide.

Let’s create a class example:

class Spaceship {
var name: String = ""
var health: Int = 0
var position: Int = 0
}

We’ve have defined a class named Spaceship and then defined three variable properties as part of the Spaceship class: name, health, and position.

But what if we want to add some functionality to our class? Well, that’s just as easy as adding a function to the class definition:

class Spaceship {
/.../
func moveLeft() {
position -= 1
}
}

Now our spaceship can move to the left every time we call the moveLeft( ) method.

Inheritance

One of the biggest differences between classes and structures is that classes have hierarchical relationship, which means that any class can have a parent and child classes called superclass and subclass respectively.

Subclasses inherit properties and methods from superclasses, but they can also augment or replace the implementation of superclass properties and methods.

class Fighter: Spaceship {
var weapon: String = ""
var remainingFirePower = 5

func fire() {
switch remainingFirePower {
case 0:
print("You have no more fire power")

default:
remainingFirePower -= 1
}
}
}

In the example above, we’ve created a new subclass called Fighter which inherits the properties of Spaceship and adds its own variable properties: weapon and remainingFirePower, as well as its own function: fire.

We didn’t have to declare the name, health and position properties again because they are already included in the Spaceship class and the Fighter subclass inherits those properties.

Override Methods and Properties

Each subclass can provide its own custom implementation of a property or method, all we have to do to override a characteristic that would otherwise be inherited is use the override keyword.

class ShieldShip: Spaceship {
var shieldStrength = 25

override func moveLeft() {
position -= 2
}
}

In this case, when the user calls the moveLeft( ) method, the ShieldShip class will have a position equal to -2 (on a x axis the left position contains the negative numbers).

We can also override properties. In the following example, we are adding a description to our Spaceship class. The description variable is a computed property. You can learn more about computed properties here.

After we have added the description variable to the Spaceship class (which is a superclass or a parent class), we will override the value of the description in the Attacker subclass (or child) like so:

//First, let's add the description variable to Spaceshipclass Spaceship {
var name: String = ""
var health = 100
var position = 0
var description: String {
"This is a spaceship"
}
}
//Now, let's override the description property and check that it works correctlyclass Attacker: Spaceship {
var bullets = 5
override var description: String {
super.description + " with \\(bullets) bullets"
}
}
let attacker = Attacker()
attacker.bullets = 8
print(attacker.description) //CONSOLE OUTPUT: This is a spaceship with 8 bullets

Override intializers

Unlike other programming languages, Swift subclasses don’t inherit their superclass intializers by default. This approach prevents a situation in which a simple initializer from a superclass is inherited by a more specialized subclass and is used to create a new instance of the subclass that isn’t fully or correctly initialized.

Let’s look at the example provided by the Swift Fundamentals book:

class Person {
let name: String
init(name: String){
self.name = name
}
}

Here we have a Person class with a name property with the name property initialized.

Following along with the example in the book, say we want to create a Student, which is a subclass of Person. We want to add to the Student subclass a property called favoriteSubject.

class Student: Person {
var favoriteSubject: String
}

Now, seeing how the favoriteSubject property has no initial value (it is not initialized), if we try to compile the code it will fail. But having initialized the name property of our superclass Person, we can call upon that initializer using super.init( ), so it will look something like this:

class Student: Person {
var favoriteSubject: String
init(name: String, favoriteSubject: String) {
self.favoriteSubject = favoriteSubject
super.init(name: name)
}
}

By calling the superclass’s initializer inside the Student subclass, we don’t have to duplicate the work that we already did when we wrote in the Person initializer.

There’s so much more to talk about when it comes to classes, but I’ll stop here for today. Until next week, keep on learning. You got this! 🙌🏻

Let me know in the comments section what you think about classes. How do Swift classes compare to other programming languages classes that you work with or are learning? Also, I’m looking forward to seeing you on Twitter and LinkedIn.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Marius Pascui

Marius Pascui

Breaking software as a QA Engineer, learning how to build software using Swift.