2011-09-22 112 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

你是對的,但我正在追求優雅。 –