Objective c 当目标类为“NSObject”时,为什么objc运行时函数“class_addMethod()”将实现添加为实例和类方法?
当我使用objc运行时函数Objective c 当目标类为“NSObject”时,为什么objc运行时函数“class_addMethod()”将实现添加为实例和类方法?,objective-c,objective-c-runtime,Objective C,Objective C Runtime,当我使用objc运行时函数class_addMethod()将实现注入NSObject的实例选择器时,它实际上将实现注入实例选择器和类选择器: @implementation HelloWorldClass - (void) helloWorld{ NSLog(@"hello world from instance method -helloWorld"); } @end // ==== // Do method injection when the application did f
class_addMethod()
将实现注入NSObject的实例选择器时,它实际上将实现注入实例选择器和类选择器:
@implementation HelloWorldClass
- (void) helloWorld{
NSLog(@"hello world from instance method -helloWorld");
}
@end
// ====
// Do method injection when the application did finish launching.
Class sourceClass = objc_getClass("HelloWorldClass");
Class targetClass = objc_getClass("NSObject");
SEL helloWorldSelector = @selector(helloWorld);
Method method = class_getInstanceMethod(sourceClass, helloWorldSelector);
IMP imp = method_getImplementation(method);
const char *methodTypeEncoding = method_getTypeEncoding(method);
class_addMethod(targetClass, helloWorldSelector, imp, methodTypeEncoding);
现在我们只需通过Objc Category声明helloWorld
的接口,并向NSObject
实例和类调用helloWorld
消息:
// Declare the interface for `helloWorld
@interface NSObject (HelloWorld)
+ (void) helloWorld;
- (void) helloWorld;
@end
// Send the `helloWorld` message to NSObject class
NSLog(@"Send the `helloWorld` message to NSObject class");
[NSObject helloWorld];
// Send the `helloWorld` message to NSObject instance
NSLog(@"Send the `helloWorld` message to NSObject instance");
[[NSObject new] helloWorld];
虽然您刚刚通过class\u addMethod()
将helloWorld
实现注入到NSObject实例选择器中,但注入后会解析类和实例消息:
=> Send the `helloWorld` message to NSObject class
=> hello world from instance method -helloWorld
=> Send the `helloWorld` message to NSObject instance
=> hello world from instance method -helloWorld
经过测试,我发现class\u addMethod()
仅当class\u addMethod()
的目标类是NSObject
时,才将实现添加到类和实例选择器中
这是objc运行时的bug还是Cocoa的bug?不,这不是bug。它定义了运行时系统的行为(尽管很模糊) 正如每个实例都有一个指向其类的
isa
实例变量一样,内存中的每个类结构都有一个指向其元类的isa
成员。正如任何给定的类都包含关于其实例的元数据(包括实例响应的方法列表),该类的元类包含关于该类本身的元数据,包括该类响应的方法列表
此外,每个类结构都有一个指向其超类的超类
成员,该成员反映在元类层次结构中(即,每个元类的超类
是另一个元类)
不过有一个主要区别:NSObject
的超类是nil
,而NSObject
元类的超类是NSObject
。换句话说,NSObject
的元类继承了NSObject
的实例方法。因此,Objective-C类不仅响应其定义的类方法,还响应NSObject
实例方法
困惑了吗?格雷格·帕克(Greg Parker)写了一篇优秀的博客,其中包括一张非常有用的图表,说明了这一切是如何联系在一起的:
编辑
唉,互联网。如果您当前使用的浏览器未显示内联PDF文档,以下是直接指向图表的链接:
这是否可以仅将实现添加到
NSObject
的实例方法列表中?使用class\u addMethod()
时,向NSObject
类和实例方法注入任何好处吗?您的代码只将实现添加到实例方法列表中,但NSObject
的元类继承了其所有实例方法;你所描述的行为就是这样的结果。就我所知,添加与类方法相同的方法不会有任何实际区别。您可以尝试ping以获得更明确的答案。非常感谢您的回答和评论。但是我仍然不明白为什么NSObject
的元类应该继承它的所有实例方法。希望能回答这个问题。:)我不确定你的问题是存在主义的还是实际的。你的意思是“为什么”吗?从“语言的设计者为什么做出这种特殊的选择?”的意义上说,为了让Objective-C类成为消息的目标,它还必须能够正确地执行实例行为。因此,其元类中的方法列表不仅必须具有类方法,还必须具有定义基本对象行为的实例方法,例如respondsToSelector:
,等等。