Почему протоколы Objective-C принимают другие протоколы? - PullRequest
12 голосов
/ 23 сентября 2011

Я видел протоколы Objective-c, определенные следующим образом:

@protocol MyProtocol <SomeOtherProtocol>
// ...
@end

Почему протоколы принимают другие протоколы? Мне особенно любопытно, почему протокол принимает протокол NSObject.

Ответы [ 2 ]

22 голосов
/ 23 сентября 2011

Это просто та же концепция, что и наследование для классов.Если протокол принимает другой протокол, он «наследует» объявленные методы этого принятого протокола.

Протокол 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;)

2 голосов
/ 23 сентября 2011

Наследование ...................

...