Protocols are confusing!


#1

Protocols are confusing to me. I’ve read the definitions (from several sources) and on that level I understand how they are constructed. What I don’t understand is why we need them. So maybe answers to these questions could help.

[ul]• Why do we need protocols?
• What if protocols didn’t exist? What problems might exist? Could these be overcome in other ways?
• When do you make your own protocol? How do you now when you need to create one? (I understand the “when you want your class to conform to a list of methods” explanation, but why would you need this - I mean after all, you are the programmer - don’t you know already what methods you are using?[/ul]

Thanks in advance.


#2

Oddly enough, I was just thinking about interfaces (aka protocols) after driving home from watching some high school students learning about C++.

This won’t be terribly well-organized, so bear with me.

You obviously understand the basics, so this piece of what I was thinking about isn’t terribly important, but it struck me that one way to describe interfaces to new programmers is to think about conceptual interfaces in real life. Not keyboards and mice, but ATMs, debit cards, and tellers for banks. Many banks treat human tellers as deprecated interfaces, but few have the courage to do away with them entirely. ATMs are great, debit cards are better, because there’s no paper, just digital cash.

The important point to those interfaces is that their standardization makes life easier for people. Switch banks? No problem. You’re still using ATMs, tellers, and debit cards.

Objective-C has the advantage over C++ in that you can send any message to any object, at least as far as the compiler is concerned. C++ demands that an object conform to a specific interface (via inheritance, typically) before you’re allowed to call methods related to that interface.

But still, protocols/interfaces give us a comfort level, a standardization that we can take advantage of. An interface specification is an agreement that you can test against, for example, so if you have a thorough set of tests, you can replace one library that conforms to that interface with a different one entirely and see if your tests still pass. If so, you’re probably good to go.

The biggest reason I like interfaces is that I utterly despise inheritance. It’s a necessary evil, but it’s rarely really necessary. It’s the lazy man’s approach to OO. (Ok, so that might be an overstatement, and I might actually have a pathology in this regard.)

To give you an example from tonight, the class I was attending is an after-school robotics project, and the instructor described their use of inheritance for sensors: accelerometers and gyroscopes are both subclasses of the sensor class. I asked whether they both implemented the same methods (messages) or actually shared any code, and it turned out the only code they shared was an interface with a processing board. So rather than inheritance, they could have defined a sensor interface, and both types could have used an interface object as a member. No inheritance needed.

I’d really like to explore Eiffel someday; all I know about it is that it takes interfaces to a new level, by declaring explicit agreements between classes. See en.wikipedia.org/wiki/Design_by_contract

Small programs don’t need interfaces, but any project of significant size, especially that requires multiple programmers, should seriously consider them.


#3

Indeed, when learning about protocols, it’s easy to ask, “Why bother?”

After all, as you point out, if you’re writing two classes that need to communicate with one another, why not just implement the methods you need and have done with it?

The primary benefits are most visible to the consumer of a particular class. For Apple’s API (such as NSURLConnection, NSXMLParser, etc.) that’s us. For classes that we write, that may be the open source community, project partners and coworkers, or even our future selves.

Autocompletion:
You may have noticed that you don’t have to declare protocol methods in a class that conforms to a protocol, but you get the benefit of autocompletion in Xcode anyway. Here, Apple has done you a favor by declaring a protocol. All you need do is declare adherence (for example as in the book) and import the appropriate header (which you’d be doing anyway), and voilà, your job as the consumer of the class just got much easier.

If Apple hadn't declared a protocol for you, you'd be fully typing out the names of each of the methods you need to implement for NSURLConnection, UITableView, et al. to work, leading to the potential for more time-costing mistakes. This leads us to:

Double-checking:
Let’s say you’re writing a class, ABCWorkhorse, that needs to periodically provide information to another object. Your coworker will be writing a class for the same application, ABCController, that needs to periodically receive messages from an ABCWorkhorse instance. You fire an email to your coworker letting him know which methods he needs to implement. If you didn’t declare a protocol in your header, your coworker may end up sending you angry emails.
Why? Without a protocol to adhere to, he didn’t get autocompletion when implementing the necessary delegate methods, so he:
(a) not only had to fully type out the names of the methods, but
(b) in doing so, typo’d the name of one of them, costing him an hour’s worth of work wondering why his methods aren’t being called by the ABCWorkhorse instance. He’ll probably think the bugs are in your class.

By declaring and adhering to a protocol when writing a class whose instances are meant to do work and report back to other objects, you get the benefit of the compiler double-checking your work for missing or typo’d (same thing, as far as the compiler knows) method names.

So, when do you write your own protocol? Most commonly, if your class does work (such as disk/network/sensor I/O or any kind of slow work such as parsing or analysis) and needs to send myriad messages to another (likely delegate) object as it works, you can save time for whoever will be using your class (even if it’s you!) by declaring a list of protocol methods for the other classes to implement.

tl;dr: autocompletion and double-checking from the compiler can save you a massive amount of time in debugging later.


#4

Protocols are contracts. The caller writes his class, the callee writes his class. After things are all wired up, the caller can call the callee. Neither programmer needs to have any other knowledge of each other’s classes.

Think about UITableView. How can it send your program a message without a protocol? The programmer that wrote UITableView doesn’t know about your program. The UITableViewDataSource protocol allows the UITableView class to send messages to whatever class you write.

Your class can implement multiple protocols without necessarily deriving from any particular base class(es). This greatly simplifies the inheritance graph in languages that support multiple inheritance (such as C++), and allows things that are impossible with only classes in languages that only support single inheritance (such as Objective-C, Java, and the .NET languages)

By the way… if you are familiar with .NET, “protocol” here is equivalent to “interface”. If you are familiar with C++, the equivalent is a class with virtual methods


#5

I know these posts are old. But thanks to the three of you with the explanations. It’s helping me understand protocols a little more. I’m sure I will get used to it more and more as I go along and finish the book.


#6

Hi Mikey

Thanks a lot for the explanation, after reading your explanation I wanted to summarize and use my own words in regards to protocols. Although your explanations make sense I usually need to word something on my own until I fully understand it.

Would it be correct to say that the basic idea behind protocols are the ability that different classes and different objects can communicate with each other? And given the fact that these protocols are defined makes it easier for various people to work on the same project?

I know this is extremely basic, but I simply try to get a handle on what the main motivation was and why protocols were introduced in the first place. Somebody had the thought: “Hey, instead of creating another class I create a protocol.”

I would also like to know if a protocol can be a delegate/helper object?

Thanks a lot, this forum is great.


#7

Protocols specify capabilities.

However, from a syntactic point of view, you can look at a protocol as a kind of re-usable list of methods. Thus, if a class adopts a specific protocol, it does not need to specify in its interface those methods listed in the protocol; it just needs to implement them.

Protocols are needed in the Objective-C Programming Language because it won’t allow you to declare a class with multiple superclasses.
For example, this is not possible:

// Bar class has no visible instance variables
@interface Bar: NSObject
- (bar_type)bar;
- (void)setBar:(bar_type)v;
@end

// Foo class has no visible instance variables
@interface Foo: NSObject
- (foo_type)foo;
- (void)setFoo:(foo_type)v;
@end

// FooBar class is both Bar and Foo
@interface FooBar: Foo, Bar    // This is an Error
...
@end

But this is possible:

@protocol BarProtocol
- (bar_type)bar;
- (void)setBar:(bar_type)v;
@end

// Bar class has no visible instance variables
@interface Bar: NSObject <BarProtocol>
@end

@protocol FooProtocol
- (foo_type)foo;
- (void)setFoo:(foo_type)v;
@end

// Foo class has no visible instance variables
@interface Foo: NSObject <FooProtocol>
@end

// FooBar class behaves as specified in the protocols: BarProtocol & FooProtocol
@interface FooBar: NSObject <BarProtocol, FooProtocol>   // This is Okay
...
@end

This is the way the language has been designed (and for good reason too.)

At the other extreme, however, the C++ Programming Language allows you to create a class with multiple superclasses, but usually this proves to be a not very smart thing to do.


#8

Thanks a lot for the explanation. I’m starting to get a grasp on the whole

Taking your words into account I went the iOS code of iTahDoodle again and another question popped up.

How would we handle these methods if no protocol was used?


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        // Because this table view only has one section,
        // the number of rows in it is equal to the number
        // of items in our tasks array
        return [tasks count];
    }

    - (UITableViewCell *)tableView:(UITableView *)tableView
             cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        // To improve performance, we reconfigure cells in memory
        // that have scrolled off the screen and hand them back
        // with new contents instead of always creating new cells.
        // First, we check to see if there's a cell available for reuse.
        
        UITableViewCell *c = [taskTable dequeueReusableCellWithIdentifier:@"Cell"];
        if (!c) {
            // ...and only allocate a new cell if none are available
            c = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:@"Cell"];
        }
        // Then we (re)configure the cell based on the model object,
        // in this case our todoItems array
        NSString *item = [tasks objectAtIndex:[indexPath row]];
        [[c textLabel] setText:item];
        // and hand back to the table view the properly configured cell
        return c;
    }

Would that be at all possible?


#9

Those methods are required by the UITableView; they enable it to communicate with its data source. Although, they must be implemented they are not required to be declared in a protocol. The protocol declaration enables the compiler and Xcode to do checks in order to ensure that methods are being used correctly.


#10

Like many others, I fully wanted to understand protocols before moving on (and especially understanding them while going through the iTahDoodle project).

Here is a quote from page 230 of Stephen G. Kochan’s Book, “Programming in Objective-C” (not trying to advertise the competition, but this definition made it really easy to understand)…

"A protocol is a list of methods that is shared among classes. The methods listed in the protocol do not have corresponding implementations; they’re meant to be implemented by someone else (like you). A protocol provides a way to define a set of methods that are somehow related with a specified name. The methods are typically documented so that you know how they are to perform and so that you can implement them in your own class definitions, if desired.

A protocol lists a set of methods, some of which you can optionally implement, and others that you are required to implement. If you decide to implement all of the required methods for a particular protocol, you are said to conform to or adopt that protocol. You are allowed to define a protocol where all methods are optional, or one where all are required."

Hope this helps someone!