Protocols are very important in Swift. When making applications in Swift, along with Object-Oriented-Programming(OOP), we also have Protocol-Oriented-Programming(POP)

Why using Protocols

Imagine that we have two struct Employee and Student. Both struct can introduce themselves using the introduce methods.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
struct Employee {
    var name: String
    func introduce() {
        print("Hello, my name is \(name). I'm an Employee")
    }
}

struct Student {
    var name: String
    func introduce() {
        print("Hello, my name is \(name). I'm an Student")
    }
}

Further more, you want to create an makeIntroduce function which take a struct as argument, and tell it to introduce itself. The problem here is, because Swift requires you to specify argument type, so you will have to create 2 functions for each struct.

1
2
3
4
5
6
7
8
9
// function for Student struct
func introduce(student: Student) {
    student.introduce()
}

// function for Employee struct
func introduce(employee: Employee) {
    employee.introduce()
}

If you have more than 2 structs, creates more and more functions will not be a fun task. We can just create a protocol, make our struct comfort it, and use our new protocol as function’s argument

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
protocol CanIntroduce {
    var name: String {get set}
    func introduce()
}

func introduce(obj: CanIntroduce) {
    obj.introduce()
}

struct Employee {
    var name: String
    func introduce() {
        print("Hello, my name is \(name). I'm an Employee")
    }
}

struct Student {
    var name: String
    func introduce() {
        print("Hello, my name is \(name). I'm an Student")
    }
}

var ash = Student(name: "Ash")
var oak = Employee(name: "Oak")

introduce(obj: ash)
// Hello, my name is Ash. I'm a Student

introduce(obj: oak)
// Hello, my name is Oak. I'm an Employee

Earlier I said that we have to make struct comfort protocol. It means that our struct must have properties and methods which are defined in that protocol.

Protocol Inheritance

One protocol can inherit from multiple protocols. That make our code more flexible and easier for maintenance

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
protocol Sport {
    var name: String {get set}
    var isOlympic: Bool {get set}
}

protocol UseBall {
    var ballNumbers: Int {get set}
}

protocol FootBall: Sport, UseBall { }

Extension

We can add more methods to existing type using extension

1
2
3
4
5
6
7
8
9
extension Int {
    var squared: Int {
        return self * self
    }
}

var a = 5
print(a.squared)
// 25

Protocol Extension

Protocol Extension allow use to add new properties and methods to your existing values that comfort the extended protocol. For example, both Array and Set comforts the Collection protocol, so we can use extension on Collection to add new methods to Array and Set, without modifying them.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
extension Collection {
    func introduce() {
        print("I have \(count) elements, they are: ")
        for ele in self {
            print(ele)
        }
    }
}

var colors: [String] = ["red", "blue", "green"]

colors.introduce()
// I have 3 elements, they are: 
// red
// blue
// green