Я видел протоколы Objective-c, определенные следующим образом:
@protocol MyProtocol <SomeOtherProtocol>
// ...
@end
Почему протоколы принимают другие протоколы? Мне особенно любопытно, почему протокол принимает протокол NSObject
.
Я видел протоколы Objective-c, определенные следующим образом:
@protocol MyProtocol <SomeOtherProtocol>
// ...
@end
Почему протоколы принимают другие протоколы? Мне особенно любопытно, почему протокол принимает протокол NSObject
.
Это просто та же концепция, что и наследование для классов. Если протокол принимает другой протокол, он "наследует" объявленные методы этого принятого протокола.
Протокол NSObject
особенно объявляет такие методы, как respondsToSelector:
. Поэтому это особенно полезно, если вы объявляете @protocol
, у которого есть методы @optional
, потому что когда вы вызовете методы на объектах, соответствующих этому протоколу, вам нужно будет проверить, отвечает ли объект методу перед его вызовом, если этот метод необязательно.
@protocol SomeProtocol <NSObject>
-(void)requiredMethod;
@optional
-(void)optionalMethod;
@end
@interface SomeObject : NSObject
-(void)testMyDelegate;
@property(nonatomic, assign) id<SomeProtocol> myDelegate;
@end
@implementation SomeObject
@synthesize myDelegate
-(void)testMyDelegate {
// Here you can call requiredMethod without any checking because it is a required (non-optional) method
[self.myDelegate requiredMethod];
// But as "optionalMethod" is @optional, you have to check if myDelegate implements this method before calling it!
if ([myDelegate respondsToSelector:@selector(optionalMethod)]) {
// And only call it if it is implemented by the receiver
[myDelegate optionalMethod];
}
}
@end
Вы можете только respondsToSelector
вызывать на myDelegate, если myDelegate
объявлен как тип, который реализует respondsToSelector
(в противном случае у вас появятся некоторые предупреждения). Вот почему протокол <SomeProtocol>
должен принять сам протокол <NSObject>
, который сам объявляет этот метод.
Вы можете думать о id<SomeProtocol>
как "любом объекте, независимо от его типа (id
)), он просто должен реализовать методы, объявленные в SomeProtocol
, включая методы, объявленные в родительском протоколе NSObject
. он может быть объектом любого типа, но , потому что SomeProtocol
принимает сам протокол NSObject
, гарантируется, что вам разрешено вызывать respondsToSelector
на этом объекте, позволяя вам проверить, реализует ли объект данный перед вызовом его, если он является необязательным.
Обратите внимание, что вы также не можете сделать SomeProtocol
принять протокол NSObject
и вместо этого объявить свою переменную как id<SomeProtocol,NSObject> myDelegate
, чтобы вы все равно могли вызвать respondsToSelector:
. Но если вы это сделаете, вам нужно будет объявить все ваши переменные таким образом везде, где вы используете этот протокол... Так что гораздо логичнее сделать SomeProtocol
непосредственно принять протокол NSObject
;)
Наследование...................