所以我在NSObject上有一个名为CustomCategory的类别,如下所示:
#import <Foundation/Foundation.h>
@interface NSObject (CustomCategory)
-(BOOL)doSomething;
@end
#import "NSObject+CustomCategory.h"
@implementation NSObject (CustomCategory)
-(BOOL)doSomething
{
NSLog(@"Done");
return NO;
}
@end
理想情况下,这将适用于这样的对象:
NSObject* object = [NSObject new];
[object doSomething];
然而,我发现它也可以这样工作,没有问题:
[NSObject doSomething];
所以我想知道,因为它是我通过类别添加的实例方法,为什么它也适用于类?
答案 0 :(得分:3)
NSObject上的实例方法也是NSObject上的类方法。
这是因为Objective-C进行动态调度的方式。如果向任何对象发送消息,则在对象类中查找方法实现。如果您向类发送消息,那么您将向类对象发送常规消息。在所谓的元类中查找实现。元类由编译器自动生成。类方法只是元类的实例方法。这由编译器透明地处理。
继承也适用于元类级别。因此,类的元类继承自其超类的元类。我们有两个并行的继承层次结构。只有像NSObject这样的根类的处理方式不同。在那里,元类不能从超类的元类继承,因为没有超类。对于根类,元类继承自根类本身。
由于类的类方法是其元类的实例方法,而NSObjects元类继承自NSObject本身,NSObject上的实例方法也是NSObject上的类方法。
答案 1 :(得分:3)
对于在运行时源中寻找此实际位置的任何人的参考,它目前位于objc-runtime-new.mm的methodizeClass
函数中:
... snip...
// Root classes get bonus method implementations if they don't have
// them already. These apply before category replacements.
if (cls->isRootMetaclass()) {
// root metaclass
addMethod(cls, SEL_initialize, (IMP)&objc_noop_imp, "", NO);
}
... snip ...
...元类的+initialize
方法将添加其实例中的所有方法实现,并将它们转换为类方法。
而且,与@Sven所说的相反,NSObject的元类实际上并不是NSObject。类在运行时始终具有单独的元类,无论它是否为root。
答案 2 :(得分:-2)
Objective C中的每个Class
都是一个对象,这意味着它是NSObject
的子类。