2011-11-06 66 views
7

在Objective C中的至少一個的執行目標C協議,可能需要協議方法或者可選的:需要一組方法

@protocol AProtocol 

@required 
-(void) aRequiredMethod; 

@optional 
-(void) anOptionalMethod; 

@end 

有一種優雅的方式來表達該對象符合協議有一組方法中的至少一個反應,我的夢想是像

@protocol AProtocol 

@anyof 
-(void) onePossibleMethod; 
-(void) anotherPossibleMethod; 

@optional 
-(void) anOptionalMethod; 

@end 

編輯:

這之中(據我所知),不可能,WOU LD有一個方法可以提高一個編譯時警告,如果聲明爲符合給定的協議一類完全由可選的方法

@protocol AProtocol 

@optional 
-(void) onePossibleMethod; 
-(void) anotherPossibleMethod; 

@end 

未能實現它們中的至少一個。

+0

回覆:'編輯'不是我見過的。如果你真的想自動化這個,你可以使用objc運行時。 – justin

回答

3

沒有在Objective-C來表示這個一個偉大的方式。如果你必須這樣做,國際海事組織最習慣和最少代碼膨脹的方式是沿着這些線:

@protocol AProtocol 

@required 
- (SEL)methodToUse; // returns one of "onePossibleMethod" or "anotherPossibleMethod" 

@optional 
-(void) onePossibleMethod; 
-(void) anotherPossibleMethod; 
-(void) anOptionalMethod; 

@en 
+0

我同意沒有很好的方法,但是我確實喜歡你的解決方案,因爲它使不熟悉代碼的開發人員能夠「官方」(即除了評論/文檔),儘管這三種方法是可選的,但你確實希望他們被執行。 – jbat100

0

您可以擁有一個動態委託屬性,該委託屬性只允許將委託分配給實現一個或另一個方法的類 - 但是這些類在運行時而不是在編譯時。你也可以創建一個bash腳本來檢查一個或另一個是否已經實現,並且這將在編譯時。

3

那麼,你與ObjC工作,所以你需要有所節制自己:

@protocol MONAbstractDataProvider 
@optional 
- (void)anOptionalMethod; 
@end 

@protocol MONDataProviderA <MONAbstractProvider> 
@required 
- (void)onePossibleMethod; 
@end 

@protocol MONDataProviderB <MONAbstractProvider> 
@required 
- (void)anotherPossibleMethod; 
@end 

在這種情況下,你必須爲調用做confromsToProtocol:測試,而不是respondsToSelector:測試對於onePossibleMethodanotherPossibleMethod。然後你通過MONAbstractDataProvider左右。只要你記得規則,這可以引入一些類型安全,但它實際上只比習慣方法稍微好一些。

因此,客戶端應該是這樣的:

- (void)update:(NSObject<MONAbstractDataProvider>*)provider 
{ 
    if ([provider conformsToProtocol:@protocol(MONDataProviderA)]) { 
     [(NSObject<MONDataProviderA>*)protocol onePossibleMethod]; 
    } 
    else if ([provider conformsToProtocol:@protocol(MONDataProviderB)]) { 
     [(NSObject<MONDataProviderB>*)provider anotherPossibleMethod]; 
    } 
    else { 
     assert(0 && "rule broken"); 
    } 
} 

這當然是假定客戶端知道所有的衍生物。

很可能,你更喜歡簡單的單一做法,如果他們都void

@protocol MONAbstractDataProvider 
@required 
- (void)performPossibleMethod; 
@optional 
- (void)anOptionalMethod; 
@end 
+0

感謝您的詳細解答,這將是在運行時進行檢查的一種方式。理想情況下,我想要的是某種編譯時檢查會引發警告(我稍微編輯了這個問題)。 – jbat100

+0

@ jbat100嗯 - 我沒有詳細說明方法的細節。編譯時檢查進入,因爲'MONAbstractDataProvider'只被採用*間接*。類只應該直接採用「MONDataProviderA」或「MONDataProviderB」,而不是「MONAbstractDataProvider」。 – justin