来自“objc.h”:
typedef struct objc_class *Class;
但在“runtime.h”中:
struct objc_class {
Class isa;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */
究竟是什么Class
?
答案 0 :(得分:10)
typedef struct objc_class *Class;
^这是objc_class
指针的前向声明。它为它提供了友好的友好名称Class
。
现在让我们来看看objc_class
结构:
(删除Objective-C 2.0检查以缩短它)
struct objc_class {
Class isa;
};
//This is really saying
struct objc_class {
struct objc_class *isa;
};
所以现在我们有一个指向自己类型的结构。但你为什么这么问?
取自Inside the Objective-C Runtime, Part 2
Class'isa(Class'Class)指向的类包含 objc_method_list中的类'类方法。了解?该 运行时中使用的术语是指一个对象是一个点 对于它的类,一个类的isa指向对象的“元类”。
那么元类'isa指针呢?那么,这指向了根 层次结构的类(大多数情况下为NSObject)。 (在基金会 框架NSObject“isa”实例的子类的每个元类 NSObject。)是的,顺便说一句,NSObject的元类'isa指向后面 到同一个结构 - 它是一个循环引用,所以没有Class'isa 永远是空的。
因此,根据该描述,当您创建一个继承自NSObject
的类时,您有一个isa
指向其类类型,该类类型指向其指向其根类的元类({{1其中包含对自身的循环引用。这解释了为什么requires two steps to determine if an object is an instance or a class。
假设您创建了以下类:
NSObject
如果你能够*遍历isa指针,你会得到以下结果:
* 您不能,因为@interface MyClass : NSObject
@end
@implementation MyClass
@end
受到保护。请参阅下面的Cocoa with Love帖子,以创建自己的实现。
isa
一旦Class c = myClassInstance->isa; //This would be the MyClass
c = c->isa; //This would be MyClass' meta class
c = c->isa; //This would be NSObjects meta class
c = c->isa; //This going forward would still be the NSObjects meta class
...
,您就会知道自己是根对象。请记住,Objective-C是C的正确超集,它本身不具有面向对象的构造,例如继承。这与其他实现细节(例如指向构成完整类层次结构的超类的指针)一起允许Objective-C提供面向对象的特性。有关类和元类的更多信息,请参阅Cocoa with Love上的帖子:What is a meta-class in Objective-C?
答案 1 :(得分:0)
关于循环引用:
如果isa被定义为不是指针如下,那么它将成为循环引用。
struct objc_class {
struct objc_class isa;
};
因为编译器无法计算objc_class的大小。
但是,在以下情况(实际定义)中,
struct objc_class {
struct objc_class *isa;
};
isa只是一个指针,所以没有问题。