لماذا استخدام (ID) في توقيع طريقة عندما يكون (nsobject *) سيكون أكثر دقة؟

StackOverflow https://stackoverflow.com/questions/1829028

  •  11-09-2019
  •  | 
  •  

سؤال

كلما قمت بتطبيق طريقة في التعليمات البرمجية الخاصة بي التي يمكن أن تقبل أو إرجاع كائنات أكثر من فئة واحدة، أحاول دائما استخدام فائقة الاستخدام الأكثر تحديدا. على سبيل المثال، إذا كنت ستقوم بتنفيذ طريقة قد ترجع NSArray * أو nsdictionary * اعتمادا على مدخلاتها، فسوف أعطي هذه الطريقة نوع المرتجلة من NSOBJECT *، لأن هذا هو الأكثر مباشرة Superclass المباشر. إليك مثال:

@interface MyParser()
- (BOOL)stringExpressesKeyValuePairs:(NSString *)string;
- (BOOL)stringExpressesAListOfEntities:(NSString *)string;
- (NSArray *)parseArrayFromString:(NSString *)string;
- (NSDictionary *)parseDictionaryFromString:(NSString *)string;
@end

@implementation MyParser
- (NSObject *)parseString:(NSString *)string {
    if ([self stringExpressesKeyValuePairs:string]) {
        return [self parseDictionaryFromString:string];
    }
    else if ([self stringExpressesAListOfEntities:string]) {
        return [self parseArrayFromString:string];
    }
}
// etc...
@end

لقد لاحظت العديد من الحالات في الأساس وغيرها من برامج برمجة التطبيقات التي تستخدمها Apple (ID) في توقيعات طريقة معينة عندما يكون (NSOBJECT *) أكثر دقة. على سبيل المثال، إليك طريقة Nspropertylistialization:

+ (id)propertyListFromData:(NSData *)data 
          mutabilityOption:(NSPropertyListMutabilityOptions)opt 
                    format:(NSPropertyListFormat *)format 
          errorDescription:(NSString **)errorString

أنواع العودة المحتملة من هذه الطريقة هي nsdata، nsstring، nsarray، nsdictionary، nsdate، nsnumber. يبدو لي أن نوع عودة (NSOBJECT *) سيكون خيارا أفضل من (معرف)، نظرا لأن المتصل سيكون قادرا على الاتصال بطرق NSOBJECT مثل الاحتفاظ بدون طالب من النوع.

أحاول عموما محاكاة التعابير التي أنشأتها الأطر الرسمية، ولكن أود أيضا أن أفهم ما يحفزهم. أنا متأكد من أن Apple لديه بعض السبب الصحيحة لاستخدام (ID) في حالات مثل هذا، لكنني فقط لا أرى ذلك. ماذا ينقصني؟

هل كانت مفيدة؟

المحلول

باستخدام معرف يخبر المحول البرمجي، سيكون كائنا من نوع غير معروف. باستخدام NSOBject، سيتوقع التحويل البرمجي منك أن تستخدم الرسائل فقط لنظام NSOBJECT. لذلك ... إذا كنت تعرف أن مجموعة تم إرجاعها ويتم صيدها كمعرف، يمكنك استدعاء ObjectatIntex: بدون تحذيرات مترجم. في حين أن تعود مع صرفة من NSOBJECT، ستحصل على تحذيرات.

نصائح أخرى

السبب الذي يستخدمه (المعرف) المستخدم في تصريحات الأسلوب هو طيها:

(1) قد تأخذ الطريقة أو تعيد أي نوع. يحتوي NSArray على أي كائن عشوائي، وبالتالي، objectAtIndex: سوف ترجع كائن من أي نوع عشوائي. يلقيها إلى NSObject* أو id <NSObject> سيكون غير صحيح لسببين؛ أولا، يمكن أن يحتوي مجموعة فرعية غير ذات NSOBject طالما أنها تنفذ مجموعة صغيرة معينة من الأساليب، وثانيا، سيتطلب نوع عودة محددة مسبقا.

(2) الهدف - ج لا يدعم تصريحات Covariant. انصح:

@interface NSArray:NSObject
+ (id) array;
@end

الآن، يمكنك الاتصال +array على كليهما NSArray و NSMutableArray. وبعد السابق إرجاع مجموعة غير قابلة للتطبيق ومجموعة صغيرة قابلة للتغيير. بسبب نقص الهدف - C لدعم إعلان Covariant، إذا تم الإعلان عن ما ورد أعلاه (NSArray*), ، سيتعين على عملاء الأسلوب الفضعي أن يلقيوا إلى `(nsmutablerray *). قبيحة، هشة، وعرضة خطأ. وبالتالي، استخدام النوع العام هو، عموما، الحل الأكثر وضوحا.

لذلك ... إذا كنت تعلن طريقة تعرض مثيل فئة محددة، Typecast صراحة. إذا كنت تعلن طريقة ستجاوز وتجاوز ذلك تجاوز فرعية و حقيقة أنها ترجع فئة فرعية ستتعرض للعملاء، ثم استخدام (id).

لا حاجة لتقديم خطأ - هناك العديد بالفعل.


لاحظ أن OBJC الآن لديه دعم محدود من التباين المشارك من خلال instancetype الكلمة الرئيسية.

بمعنى آخر NSArrayيمكن الآن الإعلان عن طريقة مجموعة صفيف +

+ (instancetype) array;

وسوف يعامل المترجم [NSMutableArray array] كما العودة an. NSMutableArray* في حين [NSArray array] سوف تعتبر العودة NSArray*.

يمكنك بالفعل استدعاء -retain على مؤشرات معرف النوع دون صب. إذا كنت تستخدم نوعا فائقا محددا، فسيتعين عليك إلقاء المؤشر في كل مرة تقوم فيها باستدعاء طريقة فرعية من أجل تجنب تحذيرات المحول البرمجي. استخدم معرف حتى لا يحذرك التحويل البرمجي وللدخول بشكل أفضل نيتك.

غالبا ما يتم إرجاع (ID) من أجل تمكين الكائنات المراد بسهولة أكبر. على سبيل المثال، في الأساليب المهيمة والراحة، تعني العودة (ID) أن أي فرعية لا يجب أن يتجاوز طرق Superclass إلا إذا كان هناك سبب محدد للقيام بذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top