为什么Objective-c协议采用其他协议?

为什么Objective-c协议采用其他协议?,objective-c,ios,protocols,nsobject,Objective C,Ios,Protocols,Nsobject,我见过Objective-c协议以以下方式定义: @protocol MyProtocol <SomeOtherProtocol> // ... @end @protocol-MyProtocol // ... @结束 为什么协议会采用其他协议?我特别好奇为什么协议会采用NSObject协议。继承………..它与类继承的概念完全相同。 如果一个协议采用另一个协议,它将“继承”该采用协议的声明方法 NSObject协议特别声明了respondsToSelector:等方法。因此,如果

我见过Objective-c协议以以下方式定义:

@protocol MyProtocol <SomeOtherProtocol>
// ...
@end
@protocol-MyProtocol
// ...
@结束

为什么协议会采用其他协议?我特别好奇为什么协议会采用
NSObject
协议。

继承………..

它与类继承的概念完全相同。 如果一个协议采用另一个协议,它将“继承”该采用协议的声明方法

NSObject
协议特别声明了
respondsToSelector:
等方法。因此,如果您声明了一个具有
@可选方法的
@协议
,这尤其有用,因为当您随后调用符合此协议的对象上的方法时,如果此方法是可选的,则需要在调用前检查对象是否响应该方法


如果
myDelegate
被声明为实现
respondsToSelector的类型,则只能在myDelegate上调用
respondsToSelector
(否则会出现一些警告)。这就是
协议需要采用
协议的原因,该协议本身声明了此方法

您可能认为
id
是“任何对象,无论其类型(
id
),它只需实现
SomeProtocol
中声明的方法,包括父协议
NSObject
中声明的方法。因此,它可以是除之外的任何类型的对象。因为
SomeProtocol
采用了
NSObject
协议本身,因此可以保证允许您调用
respondsToS此对象上的elector
,允许您在调用该对象之前检查该对象是否实现了给定的方法(如果该方法是可选的)



请注意,您也可以不使用
SomeProtocol
采用
NSObject
协议,而是将变量声明为
id myDelegate
,这样您仍然可以调用
respondsToSelector:
。但是如果这样做,您将需要在使用此协议的任何地方以这种方式声明所有变量……因此这就是much使
SomeProtocol
直接采用
NSObject
协议更合理;)

请注意,为了避免警告,严格来说没有必要使原始协议符合
NSObject
。与其使用
id myDelegate
,不如使用
NSObject*myDelegate
。是的,这也可以是一个解决方案。But然后插入对类型的依赖(即使这种情况不太可能发生,有些人可能会使用NSProxy或其他什么;我同意这是罕见的,但无论如何)因此,这有点违反了OOP的对象化原则。如果没有理由强迫用户使用显式继承NSObject的类,而只需要它实现一些给定的方法,那么为什么要强迫它呢?正确的方法是使用
NSObject
协议和
id
类型,而不是NSObject类型,to保持类型之间的弱链接,避免强类型。更准确地说,是接口继承。
@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