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

“懒惰”用于两种不同的上下文。

第一个,当批评一个类的设计时,认为一个类是无效的——它没有做足够的事情来证明它的存在。人们也称这种类为“薄”。 这可能不是你在这里的意思。

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

例如,假设我们有一个创建 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;
}

如果我们实例化一个 Employee 只是为了确定他们是否是 Founder,我们根本不需要查找他们的记录!

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

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

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

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

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

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

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

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

该课程仅在必要时才起作用——并等到最后一分钟才开始工作。这是“懒惰”!

于 2013-03-09T23:56:11.707 回答