توضیحات کامل در صفحه ی ۲۳۵ کتاب آبجکتیو سی از استفان کوخان .
برای تکمیل توضیحاتتون در رابطه با پروتوکولها ، نوعی پروتوکول به نام پروتوکول informal وجود دارد ،
این پروتوکولها بیشتر زمانی استفاده مشد که دستور @optional به آبجکتیو سی اضافه نشده بود .
به تور نحوی یعنی از لحاظ syntax اینها category هایی هستند بدون implementation ، این پروتوکولها به نام پروتوکولهای انتضاعی یا abstract protocols هم شناخته میشوند .
این پروتوکولها بیشتر برای کلاس NSObject بکار میروند .
یک از این نوع پروتوکولها ، در سرفایل NSScriptWhoseTests.h موجود هست .
برای دیدن این پروتوکول دکمه ی command رو نگه دارید و روی Foundation/Foundation.h کلیک کنید ، سپس باز هم با فشرده نگه داشتن command روی Foundation/NSScriptWhoseTests.h کلیک کنید و پروتوکول انتضاعی یا اینفورمال NSComparisonMethods را مشاهده کنید :
@interface NSObject (NSComparisonMethods)
- (BOOL)isEqualTo:(id)object;
// Implemented using isEqual:. Returns NO if receiver is nil.
- (BOOL)isLessThanOrEqualTo:(id)object;
// Implemented using compare. Returns NO if receiver is nil.
- (BOOL)isLessThan:(id)object;
// Implemented using compare. Returns NO if receiver is nil.
- (BOOL)isGreaterThanOrEqualTo:(id)object;
// Implemented using compare. Returns NO if receiver is nil.
- (BOOL)isGreaterThan:(id)object;
// Implemented using compare. Returns NO if receiver is nil.
- (BOOL)isNotEqualTo:(id)object;
// Implemented using compare. Returns NO if receiver is nil.
- (BOOL)doesContain:(id)object;
// Returns nil if receiver is not an NSArray or if array doesn't contain object.
// This operator is not working against the database.
- (BOOL)isLike:(NSString *)object;
// argument should be a string using simple shell wildcards (* and ?).
// (e.g. "Stev*" or "N?XT").
// Returns NO if receiver is not an NSString.
- (BOOL)isCaseInsensitiveLike:(NSString *)object;
@end
به نظر من استفاده از نوع پروتوکول لازم نیست و خوب هم نیست ، اما این چیزهایی که گفتم این مفهوم رو بهتر میرسونه ، که پروتوکول ، کاری جز لیست کردن متدها انجام نمیده و classless هست ، در واقع یک اکستنژن بدون implementation میباشد .
نکته ی دوم در این بحث که از قلم افتاده شد ، استفاده از conformsToProtocol برای دریافتن این مضوع که آیا آبجکت مورد نظر از پروتوکول خاصی پیروی میکنه یا نه ، میباشد .
این متد خیلی به exception handling کمک میکنه ، فرض کنید ، شی گرافیکی داریم که از پروتوکول drawing باید پیروی کنه ، و شی از نوع id باشه ، ما ۲ راه داریم یکی اینکه چندین مرتبه ، با استفاده از respondsToSelector چک کنیم که به متدهایی مثل paint یا erase جواب میده یا نه یا اینکه به یک تکه کد ساده :
if ([currentObject conformsToProtocol: @protocol (Drawing)] == YES) {
// Send currentObject paint, erase and/or outline msgs
... }
نکته ای که در کد بالا وجود داره اینه که دستور @protocol در بالا یک آبجکت از نوع پروتوکول همونجور که متد لازم داره ارسال میکنه ، کمی متفاوت ، اما مشابه با تولید آبجکت class برای متدهایی مثل isKindOfClass میباشد .
میتونید متد بالا را با تست کردن اینکه آیا هر آبجکت از NSCopying پیروی میکنه یا نه امتحان کنید .
نکته ی بعد این که عادت کنیم ، اگر آبجکت ما باید از پروتوکول خاصی استفاده کنه ، از الگوی زیر برای تعریف اون استفاده کنیم ، مخصوصا اگه id باشه :
id <Drawing> currentObject;
در اون زمان اگه مشکلی پیش بیاد ، کامپایلر آلرت میده :
warning: class ‘Square’ does not implement the ‘Drawing’ protocol
خوب ، اگه id نباشه ، نیازی نیست ، اما یادمون باشه که کامپایلر نمیدونه چی باید تو id قرار بگیره ، و همه هم میدونیم که runtime چه مصیبتی ممکنه درست کنه ، کلا همیشه باید هوای این id ها رو داشته باشید ، خطرناکن ;)