سؤال

أرغب في تجاوز طريقة في فئة Objective C لا أملك المصدر لها.

لقد بحثت في الأمر، ويبدو أن الفئات يجب أن تسمح لي بالقيام بذلك، ولكني أرغب في استخدام نتيجة الطريقة القديمة في طريقتي الجديدة، باستخدام super للحصول على نتيجة الطرق القديمة.

كلما حاولت ذلك، يتم استدعاء طريقتي، ولكن كلمة "super" لا شيء ...أي فكرة لماذا؟أقوم بتطوير iPhone باستخدام XCode 2.2 SDK.أنا بالتأكيد أعمل مع مثيل لفئة، وطريقة الفصل هي طريقة مثيل.

@implementation SampleClass (filePathResolver)
-(NSString*) fullPathFromRelativePath:(NSString*) relPath
{
    NSString *result = [super fullPathFromRelativePath: relPath];

  ... do some stuff with the old result

    return result;
}

ملاحظة وتوضيح:مما يمكنني رؤيته في Apple Docs، يبدو لي أنه يجب السماح بذلك؟

فئات المستندات على موقع Developer.apple.com:عندما تتجاوز الفئة طريقة موروثة ، يمكن للطريقة في الفئة ، كالعادة ، أن تستدعي التنفيذ الموروثة عبر رسالة إلى Super.ومع ذلك ، إذا تجاوزت الفئة طريقة موجودة بالفعل في فئة الفئة ، فلا توجد طريقة لاستدعاء التنفيذ الأصلي.

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

المحلول

تقوم الفئات بتوسيع الفئة الأصلية، لكنها لا تقوم بتصنيفها إلى فئات فرعية، وبالتالي فهي دعوة إلى super لا يجد الطريقة

ما تريد يسمى طريقة سويزلينج.لكن انتبه إلى أن التعليمات البرمجية الخاصة بك قد تؤدي إلى كسر شيء ما.هناك مقال عن ثيوكاكاو كتبها سكوت ستيفنسون حول طريقة Swizzling في وقت تشغيل Objective-C القديم، الكاكاو مع الحب لمات غالاغر يحتوي على مقال حول طريقة Swizzling في وقت تشغيل Objective-C 2.0 الجديد واستبدال بسيط له.

وبدلاً من ذلك، يمكنك فئة فرعية للفئة ثم استخدام الفئة الفرعية أو استخدامها + (void)poseAsClass:(Class)aClass ليحل محل الطبقة المتفوقة.أبل يكتب:

يمكن للطريقة التي تحددها فئة متظاهر ، من خلال رسالة إلى super، دمج طريقة الفئة الفائقة التي يتجاوزها.

كن على علم بأن شركة Apple قد إهملت poseAsClass: في نظام التشغيل Mac OS X 10.5.

نصائح أخرى

إذا سيتم الترميز ضد هذه الفئة، ببساطة إعادة تسمية محدد إلى شيء يمكن استخدام الشفرة الخاصة بك، وندعو محدد الأصلي على self:

@implementation SampleClass (filePathResolver)
-(NSString*) myFullPathFromRelativePath:(NSString*) relPath
{
    NSString *result = [self fullPathFromRelativePath: relPath];

  ... do some stuff with the old result

    return result;
}

إذا كنت تريد تجاوز تطبيق الافتراضي هذا محدد لتلك الفئة، سوف تحتاج إلى استخدام في طريقة swizzling نهج .

ليس بالضبط في الفئة ولكن هناك حل بديل عن طريق إضافة الطريقة ديناميكيًا في وقت التشغيل.يصف صموئيل ديفاغو في مقالته طريقة رائعة لإنشاء تطبيق كتلة IMP يستدعي super، ويمكن العثور على مقالته الأصلية هنا

الكود ذو الصلة هو:

#import <objc/runtime.h>
#import <objc/message.h>

    const char *types = method_getTypeEncoding(class_getInstanceMethod(clazz, selector));
    class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretained id self, va_list argp) {
        struct objc_super super = {
            .receiver = self,
            .super_class = class_getSuperclass(clazz)
        };

        id (*objc_msgSendSuper_typed)(struct objc_super *, SEL, va_list) = (void *)&objc_msgSendSuper;
        return objc_msgSendSuper_typed(&super, selector, argp);
    }), types);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top