As a beginner in Swift, structures and classes might be a little hard to understand because they are very similar to one another and they can do pretty much the same thing. In this article I'd like to give you a brief explanation of what I've learned are the main differences between classes and structures and how to choose which one to use.
Overview
In Swift, classes and structs are like a blueprint for creating objects or types. As I've said, they are very similar, and both of them can define properties to store value and methods to provide functionality.
They have a lot more in common, but let's stick with the basics here and put this into code by creating a developer type.
class Developer {
var cProperty: String
func cMethod() {}
}
struct Developer {
var sProperty: String
func sMethod() {}
}
- Whenever you create a class or structure, you're defining a new Swift type. As every Swift type, we use UpperCamelCase naming to match Swift standards.
Creating new instances
One of the things that differentiates structures from classes is that, unlike classes, we don't have to write the initializer for the structure properties. We could just create a new instance passing its initial values.
struct Developer {
var sProperty: String
func sMethod() {}
}
var newStruct = Developer(sProperty: "value")
For classes, we have to write the initializer.
class Developer {
var cProperty: String
init(cProperty: String) {
self.cProperty = cProperty
}
func sMethod() {}
}
var newClass = Developer(cProperty: "value")
That's an easy difference to understand and you don't have to worry about it too much, Xcode will always give you an error whenever you forget to write the initializer for your classes.
Let's get on with more advanced concepts and differences between structs and classes.
Key Differences
Now, we know that both classes and structs are used to create types and objects. The next question you probably have in mind is when should we use one or the other. To answer this question we need to understand what are the key differences between them.
Reference vs Value types
The main difference between a class and a structure is that a struct is a value type, and that means that it's copied whenever it's used. While the class is a reference type. Let's break this down.
Imagine we're working on a presentation together and we've got a template that we're using to create this presentation. We'll represent this template in our code using a struct.
struct PresentationTemplate {
var numberOfSlides: Int
}
Then, I give you one copy of the template and I have one copy as well.
var template = PresentationTemplate(numberOfSlides: 4)
var myTemplate = template
var yourTemplate = template
Because we're using a struct, no matter what change you make on your template, it won't affect the copy I have.
yourTemplate.numberOfSlides += 2
print(yourTemplate.numberOfSlides) // 6
print(myTemplate.numberOfSlides) // 4
Now, if we were working with classes, because classes are a reference type, every single thing that you do on your template will affect mine too, they are the same one.
class PresentationTemplate {
var numberOfSlides: Int
init(numberOfSlides: Int) {
self.numberOfSlides = numberOfSlides
}
}
var template = PresentationTemplate(numberOfSlides: 4)
var myTemplate = template
var yourTemplate = template
yourTemplate.numberOfSlides += 2
print(yourTemplate.numberOfSlides) // 6
print(myTemplate.numberOfSlides) // 6
Inheritance
Inheritance is a fundamental behavior that differentiates classes from structures. Basically, a class can inherit methods and properties from another class.
Let's create a class called Developer and add some properties and methods for it.
class Developer {
var skills = ["Write code"]
func introduce() {
print("I'm a software engineer and I can write code.")
}
}
- Because the skills property already has a value, we don't need to write an initializer function for our class.
Then, we will create a class called TechLead. This class will have everything that our class Developer has by inheriting from it, and we can check this by accessing a method or property from the Developer class.
class TechLead: Developer {}
TechLead().introduce()
// "I'm a software engineer and I can write code."
- In this case, TechLead is a subclass of the superclass Developer.
Not only a subclass can inherit from the superclass, but also provide its own custom implementation for the inherited methods and properties. This is known as overriding.
class Developer {
var skills = ["Write code"]
func introduce() {
print("I'm a software engineer and I can write code.")
}
}
class TechLead: Developer {
override func introduce() {
super.introduce()
print("Also, I lead a team of developers.")
}
}
Developer().introduce()
// "I'm a software engineer and I can write code."
TechLead().introduce()
// "I'm a software engineer and I can write code."
// "Also, I lead a team of developers."
In this case, we've used the existing superclass implementation as part of our override. But we could've totally changed the behavior of the method by removing super.introduce() from our function.
class TechLead: Developer {
override func introduce() {
print("I'm a Tech Leader and I manage a team of developers")
}
}
Developer().introduce()
// "I'm a software engineer and I can write code."
TechLead().introduce()
// "I'm a Tech Leader and I manage a team of developers"
Which one to use
If you check Swift doc, Apple recommends using structures over classes. On top of the fact that structs include many features limited to classes in other languages, they're also simpler to use, faster, and result in less memory leaks.
So, whenever you have doubt about which one to use, go with struct and consider switching to a class if you realize that you need features only classes can provide, like inheritance.
Conclusion
Michael Jordan onde said: "Get the fundamentals down and the level of everything you do will rise." That's the purpose of this article: to help you work the fundamentals and start building the foundation for coding great applications.
But this is far away from being enough. As seen in the last section, there's a lot more for you (and for me as well) to explore and understand about structures and classes in Swift. Why do structs result in fewer memory leaks? Why are they faster?
These are questions that, by design, weren't covered in here but they're great next steps for us to explore. So I'll do my part from here and I truly hope that you'll do yours from there. Great work, and see you next time! 🙋🏻♂️