In the Swift programming language, structures (structs) and classes are similar. Both are general-purpose constructs, but flexible. They’re great features for building solid, reusable code chunks for really great programs.
Here, we’ll dissect what the similarities and differences are, as well as best practices for using Swift structs and Swift classes. If you’re learning Swift (in which case, you should also check out our short tutorials on functions, loops, sets, arrays, and strings), this is definitely an aspect of programming in the language that’s worth your time.
What are Swift Structs and Classes?
Here’s how Structs and Classes are similar:
- They store values.
- Both are definitive methods for functionality.
- Structs and Classes allow access across your codebase.
- Both define initializers.
- Each can be extended elsewhere in your code.
- They conform to standard functionality protocols.
In lay-terms, structs and classes in Swift allow you to house functional logic you can reuse (much like functions). Plus, classes have added benefits:
- Can use inheritance.
- Classes can use type casting at runtime.
- Use of deinitializers to free up resources.
- Reference counting for multiple class references.
As you may have guessed, structs are simpler than classes, and most useful when you have static logic that doesn’t need to be altered. Structs are value types; classes are reference types.
How to Use Structs and Classes in Swift
We’ll riff on Apple’s official Struct and Class example:
struct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution
var interlaced = false
var frameRate = 0.0
var name: String?
}
Here, the struct is housing static data. Width and height are normal methods for identifying resolution, and are stored as variables so they can be altered as needed later on. Not all screens are created equal, after all!
The class is accessing the struct’s data for resolution, and adds other features such as interlacing, a frame-rate count, and name of the display (such as an iPhone, or a make and model of TV).
It’s important to know structs and classes only define parameters. Again, these tools house data that can be referenced. To access a struct or class, you have to initialize:
var someResolution = Resolution()
var someVideoMode - VideoMode()
Now we can access our Resolution
struct with the someResolution
initializer, and dot syntax:
print("The width of your TV is \(someResolution.width)”)
Deeper with Structs and Classes
A Swift struct is a value type. This means its value is copied when it’s used in code, which is why we note it’s most useful when defining values that don’t need to be changed, or are otherwise static when copied (such as width and height).
You would use the Resolution
struct to give yourself parameters for types of displays. If you wanted to define a high-definition display, you would do so like this:
let hd = Resolution(width: 1920, height: 1080)
You have copied the Resolution
struct’s data to the hd
constant, as well as altered the width and height. You could also frame out other types of definitions—standard, 8k, etc.—and simply copy
the struct data to each one.
Classes are reference types, which means they’re not copied. Think of it like white-out for your code, with fresh copies of the document; you always have the master copy (the class itself) but can change the data as needed. Using Apple’s example, let’s say we were defining the specs on a very decent TV:
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
Here, we’re calling our VideoMode
class, the new hd
resolution, and other class instances using dot-syntax. We are using the class logic to define the specs of our TV. Now let’s say the TV manufacturer decides to update this model with mostly the same specs but an improved framerate. It can use tenEighty
as its reference type:
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
This is using all the same specs as tenEighty
but altering the frame-rate for the new model. You’ll notice both are constants (let) but are mutable (their values can be changed). That’s because they’re referencing the class, and don’t actually store the values. That said, because alsoTenEighty
changed the framerate, the tenEighty
constant will now reference the updated framerate of ’30’ as well.
Conclusion
As you can imagine, structs and classes can be quite powerful… but should be used wisely. We advise that both be kept as minimal as possible, particularly classes. Because they can be referenced anywhere, it can be really difficult to manage all your reference points throughout your code.
If you were building a game, for example, each upgradeable weapon would be most useful in its own class. Once the player upgrades their weapon from a level 3 to 5, the most recent reference to the class would matter.