2011-09-22 100 views

回答

22

它与类的继承简单相同。 如果一个协议采用另一种协议,它会“继承”这个采用协议的声明方法。

NSObject协议特别声明方法,如respondsToSelector:。因此,如果您声明具有@optional方法的@protocol特别有用,因为当您随后将调用符合此协议的对象的方法时,如果此方法是可选的,则在调用它之前需要检查对象是否响应该方法。


@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

请注意,为避免警告,使原始协议符合'NSObject'不是必须的。而不是使用'id myDelegate',使用'NSObject * myDelegate'。 – 2011-09-22 20:42:02

+1

是的,这也可以是一个解决方案。但是它插入了对类型的依赖(即使这种情况不太可能发生,有些可能会使用NSProxy或其他类型;我同意这种情况很少见但很少见),所以它违反了OOP的抽象原则。如果没有理由强迫用户使用显式继承NSObject的类,而只需要实现某些给定的方法,为什么强制它...那么正确的方法是使用NSObject协议和类型而不是NSObject类型来保持类型之间的薄弱链接并避免强类型。 – AliSoftware

2

继承...................

+3

接口继承,更精确。 – bbum

+1

你是对的,但我正在追求优雅。 –