Data encapsulation in Swift

Keep things nice, kids

You want to be able to swap around the implementation of the main parts of your code.

One way of doing this is through encapsulation. This article will help you to understand this important coding principle.

Image for post
Image for post
Photo by fabio on Unsplash

Difficulty: Beginner | Easy | Normal | Challenging

Prerequisites:

  • Be able to produce a “Hello, World!” iOS application (guide HERE)
  • Some understanding Access Control will help (guide HERE)
  • The later part of the tutorial relies on some understanding of protocol (guide HERE)

Terminology

Abstraction: The process of removing unnecessary detail from a problem

Class: An object defined in Swift, using pass by reference semantics

Encapsulation: A way to hide the internal implementation details (perhaps by abstraction)

Encapsulation?

By having an external interface for (say) a class, and only accessing the class through that interface you would be able to change the internal working of the class without breaking anything. Wouldn’t that be Awesome?

Ok, the simplistic version. Now imagine you have any complex system that you access through a simple interface. Let us call this system an ATM machine, as in the image below

Image for post
Image for post
Photo by Nick Pampoukidis on Unsplash

When you use the ATM machine you interface through the keypad, and (if you choose) by getting a nice wad of money.

We can see this in the following Use Case diagram:

Image for post
Image for post

We can see the Teller represented as a stick-man. Now this could be a person, but if it were a machine that would not matter — the ATM user is interfacing with the system through present card, check balance and withdraw.

class ATM {
var balance: Int = 1000
func presentCard() {
print("Card returned")
}
func checkBalance() -> Int {
return balance
}
func withdraw(amount: Int) -> Int {
balance = balance - amount
return balance
}
}
let myATM = ATM()
myATM.checkBalance()

this has an unfortunate side-effect. What if we have another coder in our organisation who wants to take a bit of a short-cut in their coding (which is not you, I’m absolutely sure of that).

They might write something resembling the following for the ATM machine:

let myATM = ATM()
myATM.balance = 0
myATM.checkBalance()

Which is obviously not great. We are allowing programmers to change the balance of the ATM machine without using checkBalance. This is really not good at all.

Wheat are we going to do?

Implement encapsulation through Access Control

One answer is to implement Access Control in this case by making the balance private.

class ATM {
private var balance: Int = 1000
func presentCard() {
print("Card returned")
}
func checkBalance() -> Int {
return balance
}
func withdraw(amount: Int) -> Int {
balance = balance - amount
return balance
}
}
let myATM = ATM()
myATM.checkBalance()

Now any attempt to change balance, with our old pieces of code

let myATM = ATM()
myATM.balance = 0
myATM.checkBalance()

Will mean that Swift calmly tells us

‘balance’ is inaccessible due to ‘private’ protection level

Good stuff.

Code to a protocol

What if we wanted to exchange the internal working of the ATM from a machine to a person, or algorithmically change the working of the ATM completely?

We could code to a protocol.

protocol ATMProtocol {
func presentCard()
func checkBalance() -> Int
func withdraw(amount: Int) -> Int
}

which then the ATM conforms to

class ATM: ATMProtocol {
private var balance: Int = 1000
func presentCard() {
print("Card returned")
}
func checkBalance() -> Int {
return balance
}
func withdraw(amount: Int) -> Int {
balance = balance - amount
return balance
}
}
var myATM = ATM()
myATM.checkBalance()

Now the trick is now we can swap myATM to be a person. Mavis. (Be aware that the code below will not work on a machine. Only Mavis).

class Mavis: ATMProtocol {
private var balance: Int = 1000
func presentCard() {
// there will be instructions for Mavis here
}
func checkBalance() -> Int {
// there will be instructions for Mavis here
}
func withdraw(amount: Int) -> Int {
// there will be instructions for Mavis here
}
}
myATM = Mavis()

Wonderful!!!

Conclusion:

Encapsulation is an important principle in computer science. You might see people talk about coding to interfaces in something like Java. Well here in Swift we code to protocols. This gives us more control than the idea of simple data hiding as written above.

Trust me. This will help your coding. No argument.

Extend your knowledge

  • You can read more about encapsulation by reading the Wikipedia page (HERE)

The Twitter contact:

Any questions? You can get in touch with me here

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