I have been reading about Protocols on Objective-C but I cannot grasp this:
Consider this line
Person <CoordinateSupport> *person = [[Person alloc] init];
What is the purpose of declaring the variable to conform to the protocol CoordinateSupport? Is this something just for compile time, so Xcode can warn me if I assign something different to person or is there any purpose at run time?
I cannot see how a variable can conform to a protocol. OK, a class is easy to see, because you can have a protocol defining methods that you want some class to follow but an ivar?
I am not seeing it.
The standard pattern when declaring that a variable conforms to a protocol is to give it the "any object" type,
id. Declaring that a variable both has a specific type and conforms to a protocol is typically redundant – I'll explain why later. For now, let's talk about variables of typeid<P>, wherePis some protocol, and why they're useful. This type should be read as "an instance of any class that conforms toP."To concretize the discussion that follows, let's define a protocol:
This one is easy. A variable conforms to an Objective-C protocol when it represents an instance of a class that implements all of the required methods in the protocol.
Given this
Abacusclass, you could, of course, create a newAbacus:But you could also declare
ato just be of typeid<Adder. Remember, that means the type ofais "an instance of any class that conforms toAdder."The compiler complains because all we said about the type of
ais that it is a class that conforms toAdder, and nowhere in theAdderprotocol do we say anything about a method namedbeadCount.The purpose is for information hiding. When you want a class that conforms to
Adder, you don't need to care about what the actual class is – you just get anid<Adder>. Imagine thatAbacusis a system class, and you've written the following code:Then, in iOS 42, Apple comes up with a new innovation – the
Calculatorclass! Your friends tell you thatCalculatoradds two numbers together more than twice as fast asAbacus, and all the cool kids are using it! You decide to refactor your code, but you realize that not only do you have to change the return type ofgetAdder, but also the types of all the variables to which you assign the return value ofgetAdder! Lame. What if you had done this instead:Now, when you want to migrate to
Calculator, you just need to change the body ofgetAddertoreturn [[Calculator alloc] init]and you're done! One line. The rest of your code stays exactly the same. In that case, you have hidden the true type of the instance returned fromgetAdderfrom the rest of your code. Information hiding makes refactoring easier.Lastly, I promised to explain why something like
Abacus <Adder> *a = ...is usually redundant. What you're saying here is "ais an instance ofAbacusthat conforms toAdder." But you (and the compiler) already know thatAbacusconforms toAdder– it's right there in the interface declaration! As rmaddy points out, there are some cases where you want to talk about an instance that is either a given class, or a subclass thereof, and also specify that it conforms to a protocol, but those situations are rare, and most often specifying both a class and protocol conformance is unneeded.For more information, check out Apple's Working with Protcols guide.