id和Class的定義
runtime里面历极,聲明了id和Class的類型,簡(jiǎn)化一下如下:
struct objc_class {
struct objc_class *isa;
};
struct objc_object {
struct objc_class *isa;
};
//? (class object)
typedef struct objc_class *Class;?
// (instance of class)
typedef struct objc_object *id; ?
在objc中衷佃,id代表了一個(gè)對(duì)象趟卸。根據(jù)上面的聲明,凡是首地址是*isa的struct指針氏义,都可以被認(rèn)為是objc中的對(duì)象锄列。運(yùn)行時(shí)可以通過isa指針,查找到該對(duì)象是屬于什么類(Class)惯悠。
如果一個(gè)類:
@interface Test : NSObject {
int age;
NSString *name;
}
- (void)myAge;
+ (void)myName;
@end
@implementation Test
- (void)myAge {
printf("instance");
}
+ (void)myName {
printf("class");
}
@end
clang -rewrite-objc Test.m
會(huì)出現(xiàn)這些內(nèi)容(只是一部分)
//Class的實(shí)際結(jié)構(gòu)
struct _class_t {
struct _class_t *isa;? ? ? ? //isa指針
struct _class_t *superclass; //父類
void *cache;
void *vtable;
struct _class_ro_t *ro;? ? //Class包含的信息
};
//Class包含的信息
struct _class_ro_t {
unsigned int flags;
unsigned int instanceStart;
unsigned int instanceSize;
unsigned int reserved;
const unsigned char *ivarLayout;
const char *name;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //類名
const struct _method_list_t *baseMethods;? ? ? ? //方法列表
const struct _objc_protocol_list *baseProtocols;? //協(xié)議列表
const struct _ivar_list_t *ivars;? ? ? ? ? ? ? ? //ivar列表
const unsigned char *weakIvarLayout;
const struct _prop_list_t *properties;? ? ? ? ? ? //屬性列表
};
//Test(meta-class)
struct _class_t OBJC_METACLASS_$_Test? = {
.isa? ? ? ? = &OBJC_METACLASS_$_NSObject,
.superclass = &OBJC_METACLASS_$_NSObject,
.cache? ? ? = (void *)&_objc_empty_cache,
.vtable? ? = (void *)&_objc_empty_vtable,
.ro? ? ? ? = &_OBJC_METACLASS_RO_$_Test, //包含了類方法等
};
//Test(Class)
struct _class_t OBJC_CLASS_$_Test = {
.isa? ? ? ? = &OBJC_METACLASS_$_Test,? //此處isa指向meta-class
.superclass = &OBJC_CLASS_$_NSObject,
.superclass = (void *)&_objc_empty_cache,
.vtable? ? = (void *)&_objc_empty_vtable,
.ro? ? ? ? = &_OBJC_CLASS_RO_$_Test,? //包含了實(shí)例方法 ivar信息等
};
所有實(shí)例的isa都指向了(Class)邻邮。
(Class)是一個(gè)全局變量,其中記錄了類名克婶、成員變量信息筒严、property信息、protocol信息和實(shí)例方法列表等鸠补。
(Class)的isa指向了全局變量(meta-class)萝风,meta-class里只記錄了類名、類方法列表等紫岩。
Test *test = [[Test alloc] init];
[Test myAge];
向(instance) 發(fā)送消息myAge時(shí)规惰,運(yùn)行時(shí)會(huì)通過isa指針查找到(Class),這里保存著本類中定義的實(shí)例方法的指針泉蝌。
[Test myName];
向(Class)發(fā)送消息myName時(shí)歇万,運(yùn)行時(shí)會(huì)通過isa查找到(meta-class),這里保存著本類中定義的類方法的指針勋陪。
繼承的話贪磺,大概是這樣的:
Test *test = [[Test alloc] init];
Class cls = object_getClass(Test); //(Class)
class_getName(cls);? ? ? ? ? ? ? //"Test"
class_isMetaClass(cls);? ? ? ? ? //NO
Class meta = object_getClass(cls); //(meta-class)
class_getName(meta);? ? ? ? ? ? ? //"Test"
class_isMetaClass(cls);? ? ? ? ? ? //YES
Class meta_meta = object_getClass(meta); //NSObject(meta-class)
class_getName(meta_meta);? ? ? ? ? ? ? ? //"NSObject"
class_isMetaClass(meta_meta);? ? ? ? ? ? //YES
}