メッセージメカニズムノート

3171 ワード

この経典の事件から手に入れる


@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.
  • objc_msgSend sends a message with a simple return value to an instance of a class.
  • objc_msgSend_stret sends a message with a data-structure return value to an instance of a class.
  • objc_msgSendSuper sends a message with a simple return value to the superclass of an instance of a class.
  • 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]を実行します.概ね内部で実行される論理は、次のとおりです.
  • まず老人のところに行ってこの方法を探しに行きます.存在するかどうか、存在しない場合は探し続けます.
  • ここで、私たちはこの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です。彼こそ本当の施法者だ。