5

Objective-C のレガシー バージョンでは、objc_class 構造体は次のように実装されます。

struct objc_class {
    Class isa;
    Class super_class;
    const char *name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;
    struct objc_method_list **methodLists;
    struct objc_cache *cache;
    struct objc_protocol_list *protocols;
};

したがって、オブジェクトを表す構造体は、オブジェクトのクラスへのポインター、オブジェクトのスーパー クラスへのポインター、オブジェクトのクラス名、オブジェクトのバージョン、情報とインスタンス サイズ、オブジェクトのインスタンス変数リスト、オブジェクトのメソッド リスト、オブジェクトのキャッシュとオブジェクトのプロトコル リスト。オブジェクトを表す構造体にこれらのフィールドが存在することは、それぞれがオブジェクトに関する情報を格納しているため、かなり理解できます。

ただし、同じ struct objc_class の Objective-C 2.0 実装は次のようになります。

struct objc_class {
    Class isa;
};

したがって、このバージョンの objc_class では、構造体にフィールドが 1 つしかありません。それは、オブジェクトのクラス構造体へのポインターです。

私の質問は、オブジェクトを表す構造体に 1 つのフィールドしかないため、Objective-C 2.0 に格納されているオブジェクトに関する他の情報はどのようになっているのでしょうか?

4

1 に答える 1

7

それはすべて、新しい (まあ、それほど新しいものではありませんが) 非脆弱な ABI にあります。

基本的に、以前のように struct 内に iVar を格納する代わりに (スーパークラスが iVar レイアウトを変更すると継承が壊れます)、コンパイラは実行時と同様に、iVar リダイレクトを別のレイヤーに配置objc_setAssociatedObjectします。

これにより、いくつかの興味深いシナリオが可能になります。次の点を考慮してください。

@interface A { // part of libA.a
   id var1;
   int var2;
   float var3;
} 

@end

@interface B : A { // part of libB.a
   id var4;
}

@end

さて、将来、 class を変更するA必要があり、さらに精度が必要であると判断した場合 (たとえばvar3、 a に変換する) はどうなるでしょうか?long double

古い壊れやすい ABI では、メーカーがlibB更新するまで、私たちはめちゃくちゃにされていました。ただし、この新しい壊れにくい ABI を使用すると、動作中にこれらすべてを柔軟に変更できますlibB

理論的には、これは数サイクル遅くなる可能性がありますが、実行時に iVar を検索する簡単な方法、より柔軟なサブクラス化、およびさまざまな種類の iVar (__weakなど) のサポートが追加されます。

于 2012-08-07T00:07:52.043 に答える