苹果官方维护的objc源代码
我们常说OC是一种面向对象的语言,那么
什么是对象?
类:对同一类事物的高度抽象。类定义了这一类的属性以及行为准则(方法)。
对象:类的一个实例,是一个具体的事物。
1. runtime中的类和对象
typedef struct objc_class *Class;
typedef struct objc_object *id;
简单从定义来看:Class是一个objc_class结构类型的指针,id(任意对象)是一个objc_object结构类型的指针
再来看下这两个结构体objc_class
和objc_object
/// objc_class
struct objc_class {
Class isa;
Class super_class;
const char *name;
long version;
long info;
long instance_size;
struct objc_ivar_list *ivars;
struct objc_method_list *methodLists;
struct objc_cache *cache;
struct objc_protocol_list *protocols;
} ;
/// objc_object
struct objc_object {
Class isa;
};
objc_class和objc_object都有一个isa指针,我们知道实例的isa指针指向实例所属的类,即objc_object中的isa指针指向了objc_object所属的类objc_class,那么
objc_class中的isa指针指向哪里呢?
2. 元类 MetaClass
先看结论
每一个类本质上都是一个对象,类其实是元类(meteClass)的实例。类通过类的isa指针指向元类。所有的元类最终继承一个根元类,根元类isa指针指向本身,形成一个封闭的内循环。
看到这里我又疑惑了,实例的isa指向它所属的类,类的isa指向它的元类,类的元类是什么,是它所继承的父类吗,那么类的isa(元类)和super_class(父类)是不是有关系呢?
还是要来段代码测试一下:
Class class1 = [[NSString alloc] init].class;
Class class = [NSString class];
Class superClass = [NSString superclass];
NSLog(@"%@:%p",NSStringFromClass(class1), class1);
NSLog(@"%@:%p",NSStringFromClass(class), class);
NSLog(@"%@:%p",NSStringFromClass(superClass), superClass);
//输出结果
2018-06-02 08:17:46.802684+0800 RuntimeDemo[1129:82727] __NSCFConstantString:0x108679fe0
2018-06-02 08:17:46.802851+0800 RuntimeDemo[1129:82727] NSString:0x107abad68
2018-06-02 08:17:46.802989+0800 RuntimeDemo[1129:82727] NSObject:0x1080feea8
测试发现,NSString的元类([NSString class])并不是我以为的NSObject,而是NSString,那么实例的isa指针和类的isa指针指向到底哪里不一样呢?还是code一下看看吧
先写个方法输出Class的详细信息
- (void)getInfoFromClass:(Class)cls {
/// class_getName 获取类name
NSLog(@"%s:%p",class_getName(cls), cls);
/// class_isMetaClass用于判断Class对象是否为元类,
BOOL isMeta = class_isMetaClass(cls);
NSLog(@"%@",isMeta?@"是元类":@"不是元类");
// 成员变量
unsigned int outCount = 0;
NSLog(@"成员变量 class_copyIvarList:");
Ivar *ivars = class_copyIvarList(cls, &outCount);
for (int i = 0; i < outCount; i++) {
Ivar ivar = ivars[i];
NSLog(@"%s",ivar_getName(ivar));
}
free(ivars);
// 属性操作
NSLog(@"属性 class_copyPropertyList:");
objc_property_t * properties = class_copyPropertyList(cls, &outCount);
for (int i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSLog(@"%s", property_getName(property));
}
free(properties);
// 方法操作
NSLog(@"方法 class_copyMethodList:");
Method *methods = class_copyMethodList(cls, &outCount);
for (int i = 0; i < outCount; i++) {
Method method = methods[i];
SEL sel = method_getName(method);
NSLog(@"%@",NSStringFromSelector(sel));
}
free(methods);
}
再自定义个Person类(这里为什么不用系统的类呢,因为系统的类方法太多了,输出那么多影响观察)
#pragma mark - 定义一个类Person
@interface Person : NSObject
+ (void)staticDescription;
- (void)instanceDescription;
@end
@implementation Person
+ (void)staticDescription { }
- (void)instanceDescription { }
@end
OK,定义了一个类Person,Person包含一个类方法一个实例方法,打印一下看看
Person *person = [[Person alloc] init];
/// object_getClass用于获取对象的isa指针指向的对象。
[self getInfoFromClass:object_getClass(person)];
[self getInfoFromClass:object_getClass(Person.class)];
/// 输出结果
2018-06-02 09:32:32.473784+0800 RuntimeDemo[2398:280748] Person:0x109bf7010
2018-06-02 09:32:32.473922+0800 RuntimeDemo[2398:280748] 不是元类
2018-06-02 09:32:32.474260+0800 RuntimeDemo[2398:280748] 方法 class_copyMethodList:
2018-06-02 09:32:32.474382+0800 RuntimeDemo[2398:280748] instanceDescription
2018-06-02 09:32:32.474484+0800 RuntimeDemo[2398:280748] Person:0x109bf6fe8
2018-06-02 09:32:32.474635+0800 RuntimeDemo[2398:280748] 是元类
2018-06-02 09:32:32.474960+0800 RuntimeDemo[2398:280748] 方法 class_copyMethodList:
2018-06-02 09:32:32.475084+0800 RuntimeDemo[2398:280748] staticDescription
看到了吧,实例的isa指针指向它所属的类,类的isa指针指向的是类对象的元。类对象存的是关于实例对象的信息(变量,实例方法等),而元类对象(metaclass object)中存储的是关于类的信息(类的版本,名字,类方法等)。
所以类也是对象,是元类的对象
类对象和实例对象的区别:尽管类对象保留了一个类实例的原型,但它并不是实例本身。它没有自己的实例变量,也不能执行那些类的实例的方法(只有实例对象才可以执行实例方法)。然而,类的定义能包含那些特意为类对象准备的方法–类方法( 而不是的实例方法)。类对象从父类那里继承类方法,就像实例从父类那里继承实例方法一样。
来看下说明图:
image.png
参考链接:
https://www.jianshu.com/p/41735c66dccb
http://justsee.iteye.com/blog/2163905
http://www.zhimengzhe.com/IOSkaifa/253119.html
网友评论