簡體   English   中英

Objective-C:什么是惰性類?

[英]Objective-C: What is a lazy class?

查看 Objective-C 運行時庫源代碼,特別是objc-runtime-new.mm ,我看到了一些函數甚至注釋提到了惰性和非惰性類。 似乎沒有+load方法的類被稱為惰性類,但我不確定,很可能這是不對的。 在 Google 上搜索后,我沒有找到任何有關 Objective-C 上的惰性類的信息。

那么,什么是 Objective-C 中的惰性類? Obj-C 有這個功能嗎? 它與類實現中的+load方法有關嗎? 在上面鏈接的文件中,運行時系統調用一個名為_getObjc2NonlazyClassList的函數,以便從圖像中獲取非延遲類列表。 為什么也沒有_getObjc2LazyClassList函數?

我找到了答案:這是一個實現或不是+load方法的類。

在給定圖像文件中實現的所有類在存儲在"__DATA, __objc_classlist, regular, no_dead_strip"二進制文件部分中的列表中具有引用。 此列表允許運行時系統跟蹤存儲在此類文件中的所有類。 但是,當程序啟動時,並非所有類都需要實現。 這就是為什么當一個類實現一個+load方法時,它還在一個列表中有一個引用,該列表存儲在"__DATA, __objc_nlclslist, regular, no_dead_strip"部分中。

因此, _getObjc2NonlazyClassList檢索實現+load方法的類的列表,並且被稱為非惰性類。 _getObjc2ClassList檢索圖像文件中所有類的列表,包括沒有+load方法(並且稱為lazy)和非延遲類的類。 程序啟動時必須實現非惰性類。 另一方面,懶惰的課程不需要立即實現。 這可能會延遲,直到班級第一次收到消息為止(這就是他們被認為是“懶惰”的原因)。

順便提一下,類別也是如此。

“懶惰”用於兩種不同的環境中。

第一,在批評階級設計時,認為一個階級是無效的 - 它沒有足夠的證據來證明它的存在。 人們也把這種類稱為“薄”。 這可能不是你的意思。

其次, 惰性求值惰性實例化意味着該類僅在實際需要時執行評估屬性或初始化自身的工作。

例如,假設我們有一個創建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];
    }

現在,我們只在實際需要時加載員工記錄。 如果它們已經被加載,我們不會做任何額外的工作(除了一個方法調用)。 如果我們從不需要付款記錄,那么我們根本不需要完成工作。

該課程只有在必要時才會工作 - 並且等到最后一分鍾才開始工作。 這是“懶惰!”

這是一個基於幾個 DataImporter 和一個 DataManager 的模式,只有當第二個請求屬性時,第一個初始化是數據屬性

@interface DataImporter: NSObject
    @property (readonly) NSString* data;
@end
@implementation DataImporter
    @synthesize data;
    -(id)init {
        if (!(self = [super init])) { return nil; }
        _NSLog(@"%@", @"Importing...");
        data = @"DATA";
        _NSLog(@"%@", @"Importation completed!");
        return self;
    }
@end

@interface DataManager: NSObject {
        @private
        DataImporter* _importer;
    }
    -(NSString*)loadData;
@end
@implementation DataManager
    -(id)init {
        if (!(self = [super init])) { return nil; }
        _NSLog(@"DataManager initialized%@",@"!");
        return self;
    }
    -(NSString*)loadData {
        if (!_importer) {
            _importer = [DataImporter new];
        }
        return _importer.data;
    }
@end


DataManager* dm = [DataManager new];    //>> DataManager initialized
NSString* data = [dm loadData];         //>> Importing
                                        //>> Importation completed!
_NSLog(@"%@", data);                    //>> DATA)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM