消息机制笔记

从这个经典的案列入手


@implementation Son : Father
- (id)init
{
    self = [super init];
    if (self)
    {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
}
@end

这个答案是什么呢。开始的时候嘀咕,儿子,老子?但想想应该不是这么简单,诚然,确实没有不是坑的题,先嘀咕着,不看答案。

这是关于消息的官方解释

When it encounters a method invocation, the compiler might generate a call to any of several functions to perform the actual message dispatch, depending on the receiver, the return value, and the arguments. You can use these functions to dynamically invoke methods from your own plain C code, or to use argument forms not permitted by NSObject’s perform… methods. These functions are declared in /usr/include/objc/objc-runtime.h.

  1. objc_msgSend sends a message with a simple return value to an instance of a class.
  2. objc_msgSend_stret sends a message with a data-structure return value to an instance of a class.
  3. objc_msgSendSuper sends a message with a simple return value to the superclass of an instance of a class.
  4. objc_msgSendSuper_stret sends a message with a data-structure return value to the superclass of an instance of a class.

看不懂,继续往下,这里就要清楚Object-c里的消息机制。我们都知道消息机制的底层:

OBJC_EXPORT void objc_msgSend(void /* id self, SEL op, ... */ )
    __OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
OBJC_EXPORT void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ )

这里就大概看得出,[self class]是调用的objc_msgSend,而[super class]调用的是objc_msgSendSuper。如果前面的很常见,哪后面的到底是个什么鬼大爷。

我们先看看objc_super

struct objc_super {
    id receiver;
   Class superClass;
};


receiver还是我们的儿子对象,而superClass就是你猜的他老汉。

但我们执行[super class]。大概内部执行的逻辑是:

  1. 首先去老汉那去找这个方法。是否存在,如果不存在就继续让上找。
  2. 在这里,我们都没有去实现这个class,所以找来找去在仙人那NSObject那找到了。

而我们的[self class]也是一样的。从自己这开始找,然后去老汉那,一直往上,直到仙人那,最后都在仙人那相遇了。但我们的receiver都是儿子。所以他们折腾来回,还是最终执行的同一个方法,同一个接受者。所以结果自然也一样,打印出来都是Son。

为了验证这个,请看下例

@interface GrandFather : NSObject
- (NSString *)name;
@end
@implementation GrandFather
- (NSString *)name {
    return [NSString stringWithFormat:@"grandfather:%@",NSStringFromClass([self class])];
}
@end

@interface Father : GrandFather

@end
@implementation Father
- (NSString *)name {
    return [NSString stringWithFormat:@"father:%@",NSStringFromClass([self class])];
}
@end

@interface Son : Father
@end
@implementation Son
- (NSString *)name {
    return [NSString stringWithFormat:@"son:%@",NSStringFromClass([self class])];
}

- (void)showName {
    NSLog([NSString stringWithFormat:@"%@,%@",[self name],[super name]]);
}
@end

如果我这样调用

Son *son = [Son new];
[son showName];

这个看下结果就明了。

总结下,第一个参数只是告诉引擎从那个层级上开始找这个SEL,直到找到这个。而我们隐藏的第一个参数才是真正的Receiver。他才是真正的施法者。

你可能感兴趣的:(消息机制笔记)