OC Self 与 Super

作者: Mr__Peng__ | 来源:发表于2019-02-28 16:54 被阅读1次
    @interface PSSub : PS
    @end
    
    @implementation PSSub
    - (instancetype)init{
        self = [super init];
        if (self) {
            NSLog(@"%@", NSStringFromClass([self class]));
            NSLog(@"%@", NSStringFromClass([super class]));
        }
        return self;
    }
    @end
    

    以上代码打印结果,按照正常思维应该分别打印PSSubPS,然而实际运行结果都打印PSSub

    self是类的隐藏参数,指向当前调用方法的对象。而super并不是如我们所想是指向当前对象父类的指针。其实super是一个编译器标识符,在运行时中与self相同,指向同一个消息接受者,只是self会优先在当前类的methodLists中查找方法,而super则是优先从父类中查找。clang一下

    $ clang -rewrite-objc PS.m
    

    运行时代码如下

    static instancetype _I_PSSub_init(PSSub * self, SEL _cmd) {
        self = ((PSSub *(*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("PSSub"))}, sel_registerName("init"));
        if (self) {
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_lf_6jrk2sf11bd4pjvkrxfm_z4h0000gn_T_PS_d6ceaa_mi_0, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"))));
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_lf_6jrk2sf11bd4pjvkrxfm_z4h0000gn_T_PS_d6ceaa_mi_1, NSStringFromClass(((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("PSSub"))}, sel_registerName("class"))));
        }
        return self;
    }
    

    删除无关类型方法代码后:

    objc_msgSend((id)self, sel_registerName("class"));
    objc_msgSendSuper((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("PSSub"))}, sel_registerName("class"));
    

    查看函数定义:

    /** 
     * Sends a message with a simple return value to an instance of a class.
     * 
     * @param self A pointer to the instance of the class that is to receive the message.
     * @param op The selector of the method that handles the message.
     * @param ... 
     *   A variable argument list containing the arguments to the method.
     * 
     * @return The return value of the method.
     * 
     * @note When it encounters a method call, the compiler generates a call to one of the
     *  functions \c objc_msgSend, \c objc_msgSend_stret, \c objc_msgSendSuper, or \c objc_msgSendSuper_stret.
     *  Messages sent to an object’s superclass (using the \c super keyword) are sent using \c objc_msgSendSuper; 
     *  other messages are sent using \c objc_msgSend. Methods that have data structures as return values
     *  are sent using \c objc_msgSendSuper_stret and \c objc_msgSend_stret.
     */
    OBJC_EXPORT id objc_msgSend(id self, SEL op, ...)
        __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
    /** 
     * Sends a message with a simple return value to the superclass of an instance of a class.
     * 
     * @param super A pointer to an \c objc_super data structure. Pass values identifying the
     *  context the message was sent to, including the instance of the class that is to receive the
     *  message and the superclass at which to start searching for the method implementation.
     * @param op A pointer of type SEL. Pass the selector of the method that will handle the message.
     * @param ...
     *   A variable argument list containing the arguments to the method.
     * 
     * @return The return value of the method identified by \e op.
     * 
     * @see objc_msgSend
     */
    OBJC_EXPORT id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
        __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
    

    可知objc_msgSend函数中的self参数是指指向接收消息的类的实例的指针,即消息接受者,而op参数则是指处理该消息的selectorobjc_msgSendSuper函数中的参数super则是一个objc_super结构体,objc_super结构体定义如下:

    /// Specifies the superclass of an instance. 
    struct objc_super {
        /// Specifies an instance of a class.
        __unsafe_unretained id receiver;
    
        /// Specifies the particular superclass of the instance to message. 
        __unsafe_unretained Class super_class;
    
        /* super_class is the first class to search */
    };
    

    其中receiver是指类的实例,super_class则是指该实例的父类。可以看到在编译后的C++代码中有个__rw_objc_super结构体:

    struct __rw_objc_super { 
        struct objc_object *object; 
        struct objc_object *superClass; 
        __rw_objc_super(struct objc_object *o, struct objc_object *s) : object(o), superClass(s) {} 
    };
    

    其实即为objc_super结构体。通过(__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("PSSub"))}该段代码可知:我们把self以及PSSub的父类通过结构体的构造方法构造了一个__rw_objc_super结构体,也就是objc_super。因此objc_super结构体中的receiver既是self。所以[self class][super class]指向的是同一个消息接受者,只是self会优先从当前类的实现中寻找方法处理消息,而super则是会优先从objc_super结构体中的super_class也就是父类的实现中查找。PSPSSub中均未实现- (Class)class;方法,因此会逐级向上查找最终调用基类NSObject- (Class)class;方法,通过官方开源的NSObject- (Class)class;方法代码:

    - (Class)class{
        return object_getClass(self);
    }
    

    可知,消息接受者是self,而[self class][super class]指向的是同一个消息接受者,因此该段代码均打印PSSub

    相关文章

      网友评论

        本文标题:OC Self 与 Super

        本文链接:https://www.haomeiwen.com/subject/wrhkuqtx.html