10

Objective-C ランタイム ライブラリのソース コード、特にobjc-runtime-new.mmを見ると、いくつかの関数と、遅延クラスと非遅延クラスを参照するコメントさえありました。メソッドを持たないクラス+loadは遅延クラスと呼ばれているようですが、私にはよくわかりませんし、そうではない可能性が高いです。Google で検索した後、Objective-C の遅延クラスについては何も見つかりませんでした。

では、Objective-C の遅延クラスとは何ですか? Obj-C にはこの機能がありますか? +loadクラスの実装にメソッドが存在することに関連していますか? _getObjc2NonlazyClassList上記のリンク先のファイルで、ランタイム システムは、画像から非遅延クラスのリストを取得するために呼び出される関数を呼び出します。なぜ_getObjc2LazyClassList機能もありませんか?

4

2 に答える 2

14

私は答えを見つけました:それはすべて、メソッドを実装するかどうかというクラスに関する+loadものです。

特定の画像ファイルに実装されているすべてのクラスには、"__DATA, __objc_classlist, regular, no_dead_strip"バイナリのセクションに格納されているリストに参照があります。このリストにより、ランタイムシステムはそのようなファイルに保存されているすべてのクラスを追跡できます。ただし、プログラムの起動時にすべてのクラスを実現する必要はありません。そのため、クラスが+loadメソッドを実装すると、セクションに格納されているリストにも参照が含まれ"__DATA, __objc_nlclslist, regular, no_dead_strip"ます。

したがって、メソッドを実装し、いわゆる非レイジーと呼ばれる_getObjc2NonlazyClassListクラスのリストを取得します。メソッドを持たない(レイジーと呼ばれる)クラスとレイジーでないクラスを含む、画像ファイル内のすべてのクラスのリストを取得します。プログラムの起動時に、遅延のないクラスを実現する必要があります。一方、怠惰なクラスはすぐに実現する必要はありません。これは、たとえば、クラスが初めてメッセージを受信するまで遅延する可能性があります(これが、クラスが「怠惰」と見なされる理由です)。+load_getObjc2ClassList+load

ちなみに、同じことがカテゴリにも当てはまります。

于 2013-03-10T02:45:40.457 に答える
6

「レイジー」は、2 つの異なるコンテキストで使用されます。

1つ目は、クラスの設計を批判するとき、クラスは効果がなく、その存在を正当化するのに十分ではないと主張します。この種のクラスは「シン」とも呼ばれます。 これはおそらくあなたがここで言っていることではありません。

第二に、遅延評価遅延インスタンス化は、実際に必要なときにクラスがプロパティを評価するか、それ自体を初期化する作業のみを行うことを意味します。

たとえば、Employee オブジェクトを作成するクラスがあるとします。

 @implementation Employee
 - (id) initWithID: (IdentificationCode*) ident
 {
    self =[super init]
    if (self) {
         _records=[self retrieveEmployeeRecordsFor: ident];
         _identification=ident;
         }
    return self;
}

これは問題ありませんが、データベースからすべてのレコードを取得すると時間がかかる場合があります。また、その作業を行う必要がない場合もあります。例えば:

- (BOOL) isFounder
{
     if (indent.number<10) return YES;
     return NO;
}

従業員がファウンダーかどうかを調べるためだけに従業員をインスタンス化する場合は、従業員のレコードを検索する必要はまったくありません。

 .....
 if ([thisEmployee isFounder]) {
      [self sendCandyTo: thisEmployee.identification];
      }

一方、時にはそれらが必要になります:

- (NSArray*) payments
{
    return [self.records retrievePayStubs];
    }

そのため、 を呼び出すためだけに Employee を構築している場合isFounder、データベース ルックアップが無駄になります。しかし、それをスキップすることはできませんpayments

コンストラクターからデータベース ルックアップを取り出し、それをloadメソッドに入れます。

- (void) load
{
    if (records) return;
    self.records=[self retrieveEmployeeRecordsFor: ident];
}

- (NSArray*) payments
{
    [self load];
    return [self.records retrievePayStubs];
    }

これで、実際に必要なときにのみ従業員レコードをロードします。それらがすでにロードされている場合、追加の作業は行いません (1 つのメソッド呼び出しを除いて)。支払い記録がまったく必要ない場合は、作業を行う必要はまったくありません。

クラスは、必要な場合にのみ機能し、最後の最後まで待機します。「怠け者だ!」です。

于 2013-03-09T23:56:11.707 に答える