Протоколы в Objective-C описывают методы, которые должны реализовать классы принимающие эти протоколы. Методы описанные в протоколе не имеют собственной реализации, они реализуются в принимающем протокол классе. В других языках программирования протоколы известны как абстрактные классы и интерфейсы.
Описание протокола начинается с директивы @protocol
, за которой следует имя протокола. После этого описываются методы. Описание протокола заканчивается директивой @end
. Пример описания протокола:
@protocol TestProtocol
-(void) test;
-(void) testWithName: (NSString *) name;
@end
Протокол может описывать методы, которые должны быть реализованы обязательно или опционально. По умолчанию, все методы, описанные в протоколе, являются обязательными.
Так, методы описанные в примере являются обязательными для реализации. Также обязательные для реализации методы можно пометить с помощью директивы @requried
:
@protocol TestProtocol
@required
-(void) test;
-(void) testWithName: (NSString *) name;
@end
Данный пример эквивалентен примеру выше, все методы в протоколе являются обязательными для реализации.
Описание опциональных для реализации методов следует начинать с директивы @optional
:
@protocol TestProtocol
@required
-(void) test;
@optional
-(void) testWithName: (NSString *) name;
@end
В данном примере описан один опциональный и один обязательный метод.
Протокол может быть унаследован от произвольного количества других протоколов. Названия наследуемых протоколов задается в угловых скобках <...>
, после имени описываемого протокола:
@protocol SomeProtocol <TestProtocol>
//....
@end
Если вы решили в своем классе принять протокол, то при описание класса, принимаемые им протоколы необходимо указать в угловых скобках <...>, после названия родительского класса:
@interface TestClass : NSObject <TestProtocol, NSCoding>
@end
В данном примере мы описываем класс TestClass
, наследуемый от NSObject
и принимающий два протокола: TestProtocol
и NSCoding
. Если вы принимаете протокол и не реализуете обязательные методы, то компилятор выдаст предупреждающие сообщение.
Проверить принимает ли объект указанный протокол можно с помощью посылки этому объекту сообщения conformsToProtocol:
if ( [myObject conformsToProtocol: @protocol (TestProtocol)] ) {
// объект принимает протокол TestProtocol, поэтому смело посылаем сообщение test
[myObject test];
}
Директива @protocol
, которая используется в примере, создает объект класса Protocol
по имени.
Protocol *testProtocol = @protocol (TestProtocol);
При описании переменных класса можно указать, что они должны содержать объекты принимающие протоколы:
@interface TestClass : NSObject {
id <TestProtocol, NSCoding> _testObject;
}
@end
Здесь мы говорим компилятору, что переменная testObject
должна содержать объекты принимающие протоколы TestProtocol
и NSCoding
. Если переменной присвоить объект не реализующий указанные протоколы, то компилятор выдаст сообщение с предупреждением.
При описании методов, также как и при описании переменных, класса мы можем указать, что принимаемый аргументом объект должен принимать определенный протокол или протоколы:
@interface TestClass : NSObject
-(void) testMethod: (id <TestProtocol>) testObject;
@end