Protocols - Struggling to understand the purpose

I’m becoming more and more familiar with Swift each day, although I do find all the changes to be somewhat irritating :wink: I’ll skip that for now. I am still failing to truly understand why we use protocols at all? Yes, I’ve taken the swift apprentice course but I’m still failing to understand the purpose behind them. Keep in mind that I come from a mainframe background, so although I have substantial coding In my background, I sometimes fail to understand the “why” behind some of these concepts.

Plain English please :slight_smile:

1 Like

A protocol is a set of rules governing the exchange or transmission of data between parts of the app, in iOS / Swift it means classes, structs and enums.

The benefits of using protocols?
Think about the UITableViewDataSource.
If I declare myself as the data source of a table view, I must conform to the UITableViewDataSource - implement certain obligatory methods - and by doing so, I”ll be notified of certain events, and ready to react.

For instance, I can give the table view its number of sections or number of rows whenever this table calls the func numberOfSections(in: UITableView) or func tableView(UITableView, numberOfRowsInSection: Int)

In other words, I can do useful things thanks to my conformance. And I can do these useful things in an orderly and controlled manner. And THAT is really GREAT! :cowboy_hat_face:

iOS relies heavily on protocol and delegation to exchange data and keep things organized, and Swift nails it even more.

Is it the only way to exchange data, to keep things organized?
Well no. Using the notification center, using closures are also other techniques that allow you to exchange data.

But by using and defining your own protocols, you will keep things better organized, and probably easier to maintain.

Can you post an example using protocols that cannot be duplicated without using protocols?

I don’t think that is a fair question because you can write a complete application without creating any protocols of your own, of course you need to use and understand protocols to use Apple API’s.

The thing with protocols are that they can make your code more flexible and to change or replace the underlying logic without having to worry about other complications as long as you still follows the rules set up by the protocol.

Can you post an example of code that is more flexible using protocols?

It is a pop world. Cocoa Touch heavily relies on protocols. Try defining new methods and manually calling them to give your table view the data it needs.

As for your own code, as I said before, you can perfectly go on without defining custom protocols. In his book “iOS Apprentice”, Matthijs Hollemans uses the method reloadData instead of creating a protocol. Why does he do that?

Also. Protocols have huge advantages over inheritance. Watch the Dave Abrahams “Protocol-Oriented Programming in Swift” WWDC video. As an iOS apprentice, It is your first obligatory stop in the Pop journey. You"ll also find many excellent and concrete examples of pop on the web: Alexis Gallagher, Natasha, etc…

And there are the not so excellent articles on pop that also abound. And with the good and the bad, you’re gonna think and think and ask yourself: should I really write / use these protocols?

Decision time.

@dpalme,

Take a look at the inter-relationships between these classes:

class Animal {
    func importantMethod() {
        print("importantMethod")
    }
}

class Dog: Animal {
    var myWorker: DogOwner
    
    init(worker: DogOwner) {
        myWorker = worker
    }
    
    func go() {
        importantMethod()
        myWorker.walkDog()
        myWorker.feedDog()
    }
}

//--

class Human {
    func importantMethod() {
        print("importantMethod")
    }
}

class DogOwner: Human {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
     func walkDog() {
        print("walkDog")
    }
    
    func feedDog() {
        print("feedDog")
    }

    func goToMovies() {
        importantMethod()
        print("goToMovies")
    }
}

In the Dog class, take special note of the following line:

  var myWorker: DogOwner

The problem with that line is that the Dog class can only work in conjunction with a DogOwner type. But ponder this: does a dog care who walks it and who feeds it? For instance, can a Nanny walk a dog and feed a dog? Can a Child walk a dog and feed a dog? Can a Robot walk a dog and feed a dog? Yes, they can! But, as currently written the Dog class can’t work in conjunction with a Nanny, or a Child, or a Robot object because the Dog class specifies the type of myWorker as DogOwner. Ideally, the Dog class should really only care that the myWorker object can perform the necessary tasks. That is where Swift protocols come into play: a protocol allows you to specify what functions that an object must perform.

  1. A protocol defines a type, which means you can declare a variable that has the protocol type.

  2. A protocol can define a set of functions that an object of the protocol type must implement.

Here’s how a protocol can be employed with the Dog class:

...
...

protocol DogWorker {
    func walkDog()
    func feedDog()
}

class Dog: Animal {
    var myWorker: DogWorker  //<=== HERE
    
    init(worker: DogWorker) {
        myWorker = worker
    }
    
    func go() {
        importantMethod()
        myWorker.walkDog()
        myWorker.feedDog()
    }
}
...
...

Now, examine this line again:

var myWorker: DogWorker

By declaring myWorker to be of type DogWorker, the Dog class is now specifying a set of functions that myWorker must be able to perform. The benefit is that now a Dog class can work in conjunction with any class that has the type DogWorker, for instance:

class Nanny: Human, DogWorker {
    
    func watchChild() {
        importantMethod()
        print("watchChild")
    }
    
    func walkDog() {
        print("walkDog")
    }
    
    func feedDog() {
        print("feedDog")
    }
}

---

class Robot {
    func importantMethod() {
        print("importantMethod")
    }
}

class HouseholdRobot: Robot, DogWorker {
    func walkDog() {
        print("walkDog")
    }
    
    func feedDog() {
        print("feedDog")
    }
    
    func getMonthlyService() {
	importantMethod()
        print("getMonthlyService")
    }
}

Note that Swift does not allow multiple inheritance, and the inheritance structures in the example are already packed with parent classes. Therefore, you cannot create a DogWorker class and have the DogOwner, Nanny, and HouseholdRobot classes inherit from the DogWorker class.

The only solution that will make the Dog class more general and useful, and allow the Dog class to work in conjunction with a wider range of objects, is to create a protocol. Then the Dog class can declare its myWorker variable to be the protocol type, which will allow any class that implements the protocol to work with the Dog class.

In iOS, a UITableView employs the same strategy outlined above. A UITableView has a variable called dataSource, and the UITableView declares the dataSource variable to have the type of a protocol. That allows your ViewController class, which already has a parent class, e.g. UITableViewController, to adopt the protocol so that it can work in conjunction with the UITableView. When you control drag from a UITableView to your ViewController and hook up the dataSource connection, you are telling iOS to assign an instance of your ViewController to the UITableView’s dataSource variable. Then the UITableView uses the dataSource variable to call “worker” methods that you implemented in your ViewController.

Single inheritance with protocols is an architecture that you can find in Java as well (in Java they’re called interfaces). That architecture contrasts with C++, which allows multiple inheritance.

2 Likes

This topic was automatically closed after 166 days. New replies are no longer allowed.