antonio's blog

antonio's blog


Блог о всяком разном, связанном с разработкой ПО. Пишу редко, когда есть время и желание.

Anton Dobkin
Author

Share


Tags


Протоколы в Objective-C

Anton DobkinAnton Dobkin

Протоколы в 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
Anton Dobkin
Author

Anton Dobkin

Comments