CloseHomeAboutBlogCourse
Bob I’m an iOS instructor/blogger from S.Korea.July 14 • 5 min read • Edit

Introduction to Protocol Oriented Programming in Swift

OOP is okay, but could’ve been better

Introduction

This tutorial is also written for those who have no clear answer to the fundamental difference between Classes and Structs. We all know there is no inheritance in Structs, but why?

If you don’t know the answer, take a couple seconds to read the code below. Again, please excuse me for its format. I tried to have it as concise as possible.

class HumanClass {
  var name: String
  init(name: String) {
    self.name = name
  }
}

var classyHuman = HumanClass(name: "Bob")
classyHuman.name // "Bob"

var newClassyHuman = classyHuman // Created a "copied" object

newClassyHuman.name = "Bobby"
classyHuman.name // "Bobby"

When I changed the name property of newClassyHuman to “Bobby”, the name property of the original object, classyHuman, also changed to “Bobby”.

Now, let’s take a look at Structs

struct HumanStruct {
 var name: String
}
var humanStruct = HumanStruct(name: "Bob" )
var newHumanStruct = humanStruct // Copy and paste

newHumanStruct.name = "Bobby"
humanStruct.name // "Bob"

Do you see the difference? The change to the name property of the copied object hasn’t affected the original humanStruct object.

In Classes, when you make a copy of a variable, both variables are referring to the same object in memory. A change to one of the variables will change the other (Reference Type). In Structs, however, you simply copy and paste variables by creating a separate object (Value Type)

Bye OOP

You might be wondering why I talk about all these seemingly unrelated topics to Protocol Oriented Programming. But, before I talk about certain benefits of using POP over OOP, you just had to understand the difference between Reference type and Value type.

There are certainly benefits of using OOP, but the opposites as well.

  1. When you subclass, you have to inherit properties and methods which you may not need. Your object becomes unnecessarily bloated.
  2. When you make a lot of super classes, it becomes extremely hard to navigate between each class and fix bugs/edit.
  3. Since objects are referencing to the same place in memory, if you make a copy and create a small change its property, it can f up the rest. (Mutability due to reference)

By the way, take a look at how the UIKit framework is written in OOP

2015 WWDC_Hideous Structure

If you were to work at Apple as a software engineer for the first time, can you work with this code? I mean we developers have a hard time using it at the surface level.

One said OOP is just a modulized way to write spaghetti code. If you want to find more bad things about OOP, here are rant 1, rant 2, rant 3, rant 4.

Welcome property

You might have guessed it right, unlike Classes, the fundamental of Protocol Oriented Programming is Value Type. No more referencing. Unlike the pyramid structure you see above, POP encourages flat and non-nested code.

Just to scare you a little, I’m going to pull Apple’s definition.

“A protocol defines a blueprint of methods, properties… The protocol can then be adopted by a class, structure, or enumeration” — Apple

The only thing you need to remember right now is the word, “blueprint”. A protocol is like a basketball coach. He tells his players what to do, but he doesn’t know how to dunk a basketball.

Getting Real with POP

Firstly, let’s make a blueprint for a human.

protocol Human {
 var name: String { get set }
 var race: String { get set }
 func sayHi() }

As you can see, there is no actual “dunking” in the protocol. It only tells you that certain things exist. By the way, don’t worry about { get set } for now. It just indicates that you can set the property value to something different and also access (get) the property. Don’t worry about for now unless you are using a computed property.

Let’s make a Korean 🇰🇷 struct that adopts the protocol

struct Korean: Human {
 var name: String = "Bob Lee"
 var race: String = "Asian"
 func sayHi() { print("Hi, I'm \(name)") }
}

Once the struct adopts the Human protocol, it has to “conform” to the protocol by implementing all of the properties and methods belong to it. If not, Xcode will scream and of course, 😡 on the left side.

As you can see, you can customize all these properties as long as you meet the blueprint. You can even build a wall.

Of course, for American 🇺🇸 as well.

struct American: Human {
 var name: String = "Joe Smith"
 var race: String = "White"
 func sayHi() { print("Hi, I'm \(name)") }
}

Pretty cool? Look how much freedom you have without using those hideous “init” and “override” key words. Does it start to make sense?

Protocol Inheritance

What if you want to create a superhuman protocol that also inherits the blueprint from the Human protocol?

protocol SuperHuman: Human {
 var canFly: Bool { get set }
 func punch()
}

Now, if you make a struct or class that adopts SuperHuman, you have to meet the requirement of the Human protocol as well.

// 💪 Over 9000
struct SuperSaiyan: SuperHuman {
 var name: String = "Goku"
 var race: String = "Asian"
 var canFly: Bool = true
 func sayHi() { print("Hi, I'm \(name)") }
 func punch() { print("Puuooookkk") }
}

For those who didn’t get the reference, watch the video

Of course, you can conform to many protocols just like inherting more than on class.

// Example
struct Example: ProtocolOne, ProtocolTwo { }

Protocol Extension

Now, this is the most powerful feature of using protocol. I don’t think I need to talk too much.

// Super Animal speaks English
protocol SuperAnimal {
 func speakEnglish()
}

Add an extension to SuperAnimal

extension SuperAnimal {
 func speakEnglish() { print("I speak English, pretty cool, huh?")}
}

Now, let’s make a class that adopts SuperAnimal

class Donkey: SuperAnimal {}

var ramon = Donkey()
ramon.speakEnglish() //  "I speak English, pretty cool, huh?"

If you use an extension, you can add default functions and properties to class, struct, and enum. Isn’t it just awesome? I find this as a true nugget.

By the way, if you don’t get the reference, you can watch this

Protocol as Type (Last)

What if I told you that you could make an array that both contains a struct object and class object without type casting? 😮

That’s right.

For the example, I am going to use kangaroos that battle for getting females 👊. If you don’t believe me, watch this Kangaroo fight

protocol Fightable {
 func legKick() }

struct StructKangaroo: Fightable {
 func legKick() { print("Puuook") }
}

class ClassKangaroo: Fightable {
 func legKick() {print("Pakkkk") }
}

Now, let’s make two kangaroo objects

let structKang = StructKangaroo()
let classKang = ClassKangaroo()

Now, you can combine them together in an array.

var kangaroos: [Fightable] = [structKang, classKang]

Holy shit. For real? 😱 Watch this

for kang in kangaroos {
 kang.legKick()
}
// "Puuook"
// "Pakkkk"

Isn’t this just so beautiful? How could you have acheived this in OOP… Does the cover image make sense to you now? POP is purely gold.

Part 2

Now, let’s apply POP in real apps! Click here

Last Remark

If you found this tutorial useful, and you think I did an okay job, please ❤️ for me and share with your community. I swear, more iOS developers should implement POP! I am trying, and that’s why I wrote this, but I need your support for greater impact!

Upcoming

On this Saturday I’m going to write about the Delegate design pattern in Swift 3 using Protocol. A few people requested me to write about it, so I decided to listen to them. If you want quick updates or request me any topics, you can follow my Bob the Developer Facebook Page where I engage a lot with my readers.

If you wish to take your Swift game to the next level with memory management, advanced enums, generics, and other advanced Swift topics, you might find the intermediate course useful for your learning. You may sign up for the waiting list and receive the personal discount link here.

About Me

iOS Developer from South Korea. Feel free to follow my story on Instagram or get serious on LinkedIn