なぜ他の言語では関数呼び出しと呼ばれ、objective cではオブジェクトにメッセージを送る(またはruntimeの理解について)

2994 ワード

まず、メッセージの送信の意味をどのように理解するかを見てみましょう.
かつてObjcは特に便利で、Cocoaの中の大量のAPIに直面して、簡単なドキュメントの検索と呼び出ししか知らなかった.Objective-Cを初めて学んだとき、[receiver message]を簡単な方法として呼び出し、「メッセージを送信する」という言葉の深い意味を無視したことを覚えています.したがって、[receiver message]は、objc_msgSend(receiver, selector)メッセージにパラメータが含まれている場合、objc_msgSend(receiver, selector, arg1, arg2, ...)メッセージの受信者が対応するselectorを見つけることができれば、受信者というオブジェクトを直接実行した特定の方法に相当する.そうでなければ、メッセージが転送されるか、受信者にこのselectorに対応する実装コンテンツを一時的に動的に追加するか、いっそクラッシュを完了します.
[receiver message]は本当に単純なメソッド呼び出しではないことがわかります.これは、コンパイルフェーズで受信者にmessageというメッセージを送信することを決定し、receiveがこのメッセージにどのように応答するかを決定するだけなので、実行時に発生する状況によって決定されます.
Objective-CのRuntimeはその動的言語の特性を鋳造し、これらの深い知識は普段コードを書くのに少ないが、Objcプログラマー一人一人が理解しなければならない.
Objc Runtimeは、Cがオブジェクト向けの機能を持ち、プログラムの実行時にクラス、オブジェクト、およびそれらを作成、チェック、変更する方法を備えています.runtimeの一連の方法を用いて実現することができる.
ちなみにOCのクラスのデータ構造/usr/include/objc/runtimeを添付します.h
   struct objc_class {
    Class isa OBJC_ISA_AVAILABILITY; //isa    Meta Class,  Objc         Object,        ,r       untime    Meta Class,     [NSObject alloc]     ,            Class Object

    #if !__OBJC2__
    Class super_class OBJC2_UNAVAILABLE; //   
    const char *name OBJC2_UNAVAILABLE; //   
    long version OBJC2_UNAVAILABLE; //       ,   0
    long info OBJC2_UNAVAILABLE; //    ,            
    long instance_size OBJC2_UNAVAILABLE; //          
    struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; //          
    struct objc_method_list **methodLists OBJC2_UNAVAILABLE; //        
    struct objc_cache *cache OBJC2_UNAVAILABLE; //     ,           isa        ,    method       Lists   ,  cache ,                  。
    struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; //     
    #endif

    } OBJC2_UNAVAILABLE;

OCのクラスのオブジェクトインスタンスのデータ構造(/usr/include/objc/objc.h)は、
    typedef struct objc_class *Class;

    /// Represents an instance of a class.

    struct objc_object {

        Class isa  OBJC_ISA_AVAILABILITY;

    };

    /// A pointer to an instance of a class.

    typedef struct objc_object *id;

オブジェクトにメッセージを送信すると、Runtimeライブラリはobjectのisaポインタに基づいてこのインスタンスobjectが属するクラスを見つけ、クラスのメソッドリストおよび親メソッドリストで対応するメソッドを探して実行します.idはobjc_ですobject構造タイプのポインタで、このタイプのオブジェクトを任意のオブジェクトに変換できます.
次に、メッセージ送信の関数:objc_を見てみましょう.msgSend関数
引用文ではobjc_msgSendで少し紹介しましたが、objc_のように見えますmsgSendはデータを返しますが、実はobjc_msgSendはデータを返さないで、あなたの方法が呼び出されてデータを返しました.次のメッセージ送信手順について詳しく説明します.
1.このselectorが無視されるかどうかを検出します.例えばMac OS X開発では,ゴミ回収があればretain,releaseといった関数を無視している.2.このtargetがnilオブジェクトかどうかを検出します.ObjCの特性は、無視されるため、nilオブジェクトに対して任意の方法を実行することを許可することです.3.上の2つが過ぎたら、このクラスのIMPを探し始め、cacheから探し、見つけ終わったら対応する関数にジャンプして実行します.4.cacheが見つからない場合は、方法を探して発表します.5.分発表が見つからない場合はスーパークラスの分発表まで探し、NSObjectクラスが見つかるまで探します.6.まだ見つからない場合は、ダイナミックメソッド解析に入ります.後述します.
動的メソッド解析resolveThisMethodDynamicallyメッセージ転送forwardingTargetForSelector
詳細はhttps://app.yinxiang.com/shard/s10/nl/146175/7925ae66-03f7-487c-83a7-26c519aa897b/