我見過這樣定義的Objective-C的協議:爲什麼Objective-c協議採用其他協議?
@protocol MyProtocol <SomeOtherProtocol>
// ...
@end
爲什麼協議採取其他協議?我特別好奇爲什麼協議會採用NSObject
協議。
我見過這樣定義的Objective-C的協議:爲什麼Objective-c協議採用其他協議?
@protocol MyProtocol <SomeOtherProtocol>
// ...
@end
爲什麼協議採取其他協議?我特別好奇爲什麼協議會採用NSObject
協議。
它與類的繼承簡單相同。 如果一個協議採用另一種協議,它會「繼承」這個採用協議的聲明方法。
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
協議;)
請注意,爲避免警告,使原始協議符合'NSObject'不是必須的。而不是使用'id myDelegate',使用'NSObject * myDelegate'。 –
2011-09-22 20:42:02
是的,這也可以是一個解決方案。但是它插入了對類型的依賴(即使這種情況不太可能發生,有些可能會使用NSProxy或其他類型;我同意這種情況很少見但很少見),所以它違反了OOP的抽象原則。如果沒有理由強迫用戶使用顯式繼承NSObject的類,而只需要實現某些給定的方法,爲什麼強制它...那麼正確的方法是使用NSObject協議和類型而不是NSObject類型來保持類型之間的薄弱鏈接並避免強類型。 – AliSoftware