OC对象的分类

对象的isa指向哪里?
类信息存放在哪里?

Objective-C对象,简称OC对象,分为三类:

  • instance对象(实例对象)
  • class对象(类对象)
  • meta-class对象(元类对象)

instance对象就是通过类alloc出来的对象,每次alloc都会产生新的instance对象,占据不同的内存

instance对象在内存中存储的信息有哪些?

  • isa指针
  • 成员变量

每个类在内存中有且只有一份对象。
class对象在内存中存储的信息有哪些?

  • isa指针
  • superclass指针
  • 类的属性信息(@property)、类的对象方法信息(instance_method)、类的成员变量信息(ivar)、类的协议信息(protocol)

每个类在内存中有且只有一份meta-class对象。
meta-class对象和class对象的内存结构中是一样的只是用途不一样,在内存中存储的信息包括:

  • isa指针
  • superclass指针
  • 类的类方法信息(class method)
  • ......

调用对象方法和类方法的过程

对象方法调用过程

  • instance的isa指向class
  • 当调用对象方法时,通过instance的isa找到class,最后找到对象方法的实现进行调用

类方法调用过程

  • class的isa指向meta-class
  • 当调用类方法时,通过class的isa找到meta-class,最后找到类方法的实现进行调用

superclass的调用过程


@interface Person : NSObject

@interface Student : Person

当Student的instance对象要调用Person中的对象方法时,会先通过isa指针找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用。

当Student的class要调用Person中的类方法时,会先通过isa指针找到Student的meta-class,然后通过superclass找到Person的meta-class,最后找到类方法的实现进行调用。

image.png
  • instance的isa指向class
  • class的isa指向meta-class
  • meta-class的isa指向基类的meta-class
  • class的superclass指向父类的isa
  • 如果没有父类,superclass指向nil
  • meta-class的superclass指向父类的meta-class
  • 基类的meta-class的superclass指向基类的class

看两个函数

OBJC_EXPORT BOOL class_isMetaClass(Class cls) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);

OBJC_EXPORT Class object_getClass(id obj) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);

class_isMetaClass用于判断Class对象是否为元类,object_getClass用于获取对象的isa指针指向的对象。

再看如下代码:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [[Person alloc] init];
        //输出1
        NSLog(@"%d", [p class] == object_getClass(p));
        //输出0
        NSLog(@"%d", class_isMetaClass(object_getClass(p)));
        //输出1
        NSLog(@"%d", class_isMetaClass(object_getClass([Person class])));
        //输出0
        NSLog(@"%d", object_getClass(p) == object_getClass([Person class]));
    }
    return 0;
}

通过代码可以看出,一个实例对象通过class方法获取的Class就是它的isa指针指向的类对象,而类对象不是元类,类对象的isa指针指向的对象是元类。

思考题

@interface Person : NSObject
+ (void)test;
@end
@implementation Person
@end

@interface NSObject (Test)
+ (void)test;
@end
@implementation NSObject (Test)
-(void)test{
    NSLog(@"NSObject+Test");
}
@end

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

以上代码能运行成功吗?

答案:能运行成功,从isa,superclass去考虑(通过objc_msgSend查找方法时,不知道是实例方法还是类方法)

你可能感兴趣的:(OC对象的分类)