Objective-C:什么是懒惰的课程?

Lui*_*BOL 10 objective-c lazy-evaluation objective-c-runtime

查看Objective-C运行时库源代码,特别是在objc-runtime-new.mm,我看到了一些函数甚至注释引用了懒惰和非惰性类.似乎没有一个类+load的方法被称为懒类,但我不知道这一点,并最有可能是不正确的.在Google上搜索后,我没有在Objective-C上找到任何有关惰性类的内容.

那么,什么是Objective-C中的惰性类?Obj-C有这个功能吗?它是否与+load类实现中存在方法有关?在上面链接的文件中,运行时系统调用一个被调用的函数_getObjc2NonlazyClassList,以便从图像中获取非惰性类的列表.为什么没有_getObjc2LazyClassList功能呢?

Lui*_*BOL 13

我找到了答案:这是一个实现或不是+load方法的类.

在给定图像文件中实现的所有类在存储在"__DATA, __objc_classlist, regular, no_dead_strip"二进制文件部分中的列表中具有引用.此列表允许运行时系统跟踪存储在此类文件中的所有类.但是,当程序启动时,并非所有类都需要实现.这就是为什么当一个类实现一个+load方法时,它在一个存储在该"__DATA, __objc_nlclslist, regular, no_dead_strip"部分中的列表中也有一个引用.

因此,_getObjc2NonlazyClassList检索实现+load方法的类列表,并称为非惰性类._getObjc2ClassList检索图像文件中所有类的列表,包括没有+load方法(并且称为惰性)和非惰性类的类.程序启动时必须实现非惰性类.另一方面,懒惰的课程不需要立即实现.这可能会延迟,直到班级第一次收到消息为止(这就是他们被认为是"懒惰"的原因).

顺便提一下,类别也是如此.


Mar*_*ein 5

"懒惰"用于两种不同的环境中.

第一,在批评阶级设计时,认为一个阶级是无效的 - 它没有足够的证据来证明它的存在.人们也把这种类称为"薄". 这可能不是你的意思.

其次,惰性求值惰性实例化意味着该类仅在实际需要时执行评估属性或初始化自身的工作.

例如,假设我们有一个创建Employee对象的类.

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

这很好,但从数据库中检索所有记录可能会很慢.有时我们不需要做这项工作.例如:

- (BOOL) isFounder
{
     if (indent.number<10) return YES;
     return NO;
}
Run Code Online (Sandbox Code Playgroud)

如果我们实例化一个员工只是为了找出他们是否是创始人,我们根本不需要查看他们的记录!

 .....
 if ([thisEmployee isFounder]) {
      [self sendCandyTo: thisEmployee.identification];
      }
Run Code Online (Sandbox Code Playgroud)

另一方面,有时我们需要它们:

- (NSArray*) payments
{
    return [self.records retrievePayStubs];
    }
Run Code Online (Sandbox Code Playgroud)

因此,如果我们构建一个只是为了调用的Employee isFounder,我们就会浪费数据库查找.但我们不能只是跳过它,因为payments需要它.

我们所做的是从构造函数中取出数据库查找并将其放入load方法中.

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

- (NSArray*) payments
{
    [self load];
    return [self.records retrievePayStubs];
    }
Run Code Online (Sandbox Code Playgroud)

现在,我们只在实际需要时加载员工记录.如果它们已经被加载,我们不会做任何额外的工作(除了一个方法调用).如果我们从不需要付款记录,那么我们根本不需要完成工作.

该课程只有在必要时才会工作 - 并且等到最后一分钟才开始工作.这是"懒惰!"