为什么编译器不会在[NSObject init]上返回错误

时间:2017-08-14 22:06:19

标签: objective-c xcode nsobject foundation

当我尝试编译以下代码时:

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        [NSObject init];
    }
    return 0;
}

编译器让它构建,然后应用程序在运行时崩溃,但有以下异常:

2017-08-14 14:56:07.937859-0700 NSObjectInit[30512:11241814] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSObject<0x7fff9fd83140> init]: cannot init a class object.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff818e32cb __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x00007fff966f348d objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff8196517f +[NSObject(NSObject) init] + 127
    3   NSObjectInit                        0x0000000100000f2d main + 61
    4   libdyld.dylib                       0x00007fff96fd9235 start + 1
    5   ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

据我所知,NSObject类中有+ init方法,但是我没有在公共头文件中找到它,如果它是私有的,编译器应该告诉我们没有这样的方法。有什么想法为什么编译器让我们构建这个代码?

2 个答案:

答案 0 :(得分:6)

类本身就是对象。每个类都有一个隐式的“元类”,该类是该元类的唯一实例。我们通常认为“类Foo上的类方法”也是类meta-Foo上的实例方法。

在另一个怪癖中,类层次结构的根类的元类是根类本身的子类。这是元 - NSObject继承自NSObject。类NSObject是它自己的一个实例!

因此,NSObject的任何实例方法也是NSObject的类方法。也就是说,它可以在NSObject类本身上调用。这就是编译器对[NSObject init]没有问题的原因。

http://sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html

答案 1 :(得分:0)

正如Ken Thomases所说,这种行为与NSObject的元类有关。简而言之,我们可以在类的实例上调用NSObject的所有方法。

  

对于NSObject层次结构中的所有实例,类和元类,   这意味着所有NSObject实例方法都是有效的。为了   类和元类,所有NSObject类方法也都有效。

查看更多详情here。这个diagram也很有用。