Protocols declare methods that can be implemented by any class.
6.1 Declaring Interfaces for Others to Implement
Informal and formal protocols declare methods that are independent of any specific class, but which any class, and perhaps many classes, might implement.
A protocol is simply a list of method declarations, unattached to a class definition.
Objects can be grouped into types not just on the basis of similarities due to the fact that they inherit from the same class, but also on the basis of their similarity in conforming to the same protocol.
6.5 Formal Protocols
The Objective-C language provides a way to formally declare a list of methods(including declared properties) as a protocol.
6.5.1 Declaring a Protocol
You declare formal protocol with the @protocol directive:
@protocol ProtocolName
method declarations
@end
Example:
@protocol MyXMLSupport
- initFromXMLRepresentation: (NSXMLElement *)XMLElement;
@property (nonatomic, readonly) (NSXMLElement *)XMLRepresentation;
@end
6.5.2 Optional Protocol Methods
You can use @optional and @required to partition your protocol into sections. If you do not specify any keyword, the default is@required.
@protocol MyProtocol
-(void)requiredMethod;
@optional
-(void)anOptionalMethod;
@required
-(void)anotherRequiredMethod;
@end
6.6 Informal Protocols
In addition to formal protocols, you can also define an informal protocol by grouping the methods in a category declaration:
@interface NSObject( MyXMLSupport )
- initFromXMLRepresentation: (NSXMLElement *)XMLElement;
@property (nonatomic, readonly) (NSXMLElement *)XMLRepresentation;
@end
Informal protocols are typically declared as categories of the NSIObject class.
6.8 Adopting a Protocol
A class is said to adopt a formal protocol if in its declaration it lists the protocol within angle brackets after the superclass name:
@interface ClassName : ItsSuperclass < protocol list >
Categories adopt protocols in much the same way:
@interface ClassName ( CategoryName ) <protocol list>
A class can adopt more than one protocol; names in the protocol list are separated by commas:
@interface Formatter : NSObject < Formatting, Prettyifying >
A class or category that adopts a protocol must
implement all the required methods the protocol declares, otherwise the compiler issues a warning.
A class or category that adopts a protocol must import the header file where the protocol is declared. The methods declared in the adopted protocol are not declared elsewhere in the class or category interface.
It is possible for a class to simply adopt protocols and declare no other methods:
@interface Formatter : NSObject < Formatting, Prettifying >
@end
6.9 Conforming to a Protocol
A class is said to conform to a formal protocol if it adopts the protocol or inherits from another class that adopts it.It's possible to check whether an object conforms to a protocol by sending is aconformsToProtocol: message
if ( ! [receiver conformsToProtocol:@protocol(MyXMLSupport)] )
{
// Object does not conform to MyXMLSupport protocol
}
The
conformsToProtocol: test is like the
respondsToSelector: test for a single method.
6.10 Type Checking
Type declarations for objects can be extended to include formal protocols.
In a type declaration, protocol names are listed between angle brackets after the type name:
- (id <Formatting>)formattingService;
id <MyXMLSupport> anObject;
Just as static typing permits the compiler to test for a type based on the class hierarchy, this syntax permits the compiler to test for a type based on conformance to a protocol.
The compiler can make sure only objects that conform to the protocol are assigned to the type.
Protocols can't be used to type class objects. Only instances can be statically typed to a protocol, just as only instance can be statically typed to a class. (However, at runtime, both classes and instances will respond to a conformsToProtocol: message)
6.11 Protocols Within Protocols
One protocol can incorporate other protocols using the same syntax that classes use to adopt a protocol:
@protocol ProtocolName < protocol list >
All the protocols listed between angle brackets are considered part of the ProtocolName protocol.
6.12 Referring to Other Protocols
Sometimes you may write code like this:
File A:
#import "B.h"
@protocol A
- foo:(id <B>)anObject;
@end
File B:
#import "A.h"
@protocol B
- bar:(id <A>)anObject;
@end
In such case, you should use the @protocol directive to make a forward reference to the needed protocol to avoid circularity results.
// redesign File A
@protocol B
@protocol A
- foo:(id <B>)anObject;
@end