面向对象

2018-09-27  本文已影响9人  蔚尼

一. OC的本质

OC本质

1.NSObject的底层实现

一个NSObject对象占用多少内存?

2.NSObject对象的本质

NSObject里面存放了isa指针和成员变量;
没有存放方法;

创建student对象继承NSObject NSObject对象
  • student对象的大小占用16个字节:8个字节(父类的大小:isa指针大小)+4个字节*2(两个int类型,每个int类型占用4个字节)。
  • 一个对象占用的大小 = 父类的大小+子类里面字段的大小。
  • 占用的最小是16个字节,如果不够16,系统会自动补齐为16个字节
  • 为了内存对齐。结构体的大小,占用的字节必须是最大成员(8个字节)的倍数。配合iOS操作系统,分配的内存空间是16的倍数

思考:创建一个Person:NSObeject,Student:Person。一个Person对象、一个Student对象占用多少内存空间?

继承结构 继承结构
  1. 一个NSObject分配了16个字节,使用了8个字节;
  2. Person对象大小为NSobect使用字节的大小8 + _age大小 4 = 12,为了对齐,所以结构体占用了16个字节;
  3. Student对象大小为Person使用的大小12个字节+_no大小4 = 16个字节,刚好是16的倍数,所以不进行补齐。所以Student占用了16个字节。

思考:创建一个Person:NSObeject,里面创建三个int类型的成员变量。一个Persont对象占用多少内存空间?

image.png image.png
  1. 8个字节+ 4个字节 * 3 = 20 个字节。为了结构体对齐,需要是8的倍数。所以是占用了24个字节;
    2.但是为了操作系统的对齐,分配的空间需要是16的倍数,所以是32个字节。
  • 创建一个实例对象,至少需要多少内存?(结构体至少需要的内存,8的倍数;占用的字节)
    -#import <objc/runtime.h>
    class_getInstanceSize([NSObject class]);
  • 创建一个实例对象,实际上分配了多少内存?(分配的空间,16的倍数)
    -#import <malloc/malloc.h>
    malloc_size((__bridge const void *)obj);

二.OC对象的分类

1. instance对象(实例对象)

instance对象就是通过类alloc出来的对象,每次调用alloc都会产生新的instance对象

instance对象在内存中存储的信息包括:
1.isa指针
2.其他成员变量

两个NSObject对象

object1、object2是NSObject的instance对象(实例对象)

2. class对象(类对象)

class对象的获取
  • objectClass1 ~ objectClass5都是NSObject的class对象(类对象)
  • 它们是同一个对象。每个类在内存中有且只有一个class对象

class对象在内存中存储的信息主要包括:

  1. isa指针
  2. superclass指针
  3. 类的属性信息(@property)、类的对象方法信息(instance method)
  4. 类的协议信息(protocol)、类的成员变量信息(ivar)
    这里的属性是指它的类型、名等信息;
class类对象.png

3. meta-class对象(元类对象)

把类对象传进去,就可以获得元类对象


获取元类

每个类在内存中有且只有一个meta-class对象

meta-class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括
1.isa指针
2.superclass指针
3.类的类方法信息(class method)
......

元类对象.png

以下代码获取的objectClass是class对象,并不是meta-class对象(通过class获得的都是类对象)

获取类对象 判断是否为元类

三.isa指针

1. isa指针

isa指针

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

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

2. superclass

2.1 类对象的superclass指针

类对象的superclass指向其父类的类对象
如下:创建Person:NSObject;Student:Person
Student类对象superclass指向Person的类对象,Person类对象的superclass指向NSObject的类对象。

superclass指向
  • superclass用处:
    当Student的instance对象要调用Person的对象方法时,会先通过isa找到Student的class,然后通过superclass找到Person的class,最后找到对象方法的实现进行调用;

如下:student实例对象调用父类person的test方法。
student实例对象通过isa指针找到student类对象;
student类对象通过superclass找到person类对象;
调用person类对象里面的test方法。

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        Student *student = [[Student alloc] init];
        [student test];
        [student personInstanceMethod];
        [student init];
        
        [Student studentClassMethod];
        [Student personClassMethod];
        [Student load];
        [Student abc];
      
    }
Person:
@interface Person : NSObject <NSCopying>
{
    @public
    int _age;
}
@property (nonatomic, assign) int no;
- (void)personInstanceMethod;
+ (void)personClassMethod;
@end

@implementation Person

- (void)test
{
    
}

- (void)personInstanceMethod
{
    
}
+ (void)personClassMethod
{
    
}
- (id)copyWithZone:(NSZone *)zone
{
    return nil;
}
@end

Student:
@interface Student : Person <NSCoding>
{
@public
    int _weight;
}
@property (nonatomic, assign) int height;
- (void)studentInstanceMethod;
+ (void)studentClassMethod;
@end

@implementation Student
- (void)test
{
    
}
- (void)studentInstanceMethod
{
    
}
+ (void)studentClassMethod
{
    
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
    return nil;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    
}
@end
    return 0;
}

2.2 元类对象的superclass指针

meta-class(元类)对象的superclass指针,指向父类的元类对象

元类对象的isa指针

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

如上面的例子中:
Student调用Person的类方法personClassMethod: [Student personClassMethod];

Student类对象通过isa指针找到Student的元类对象;
Student的元类对象通过superclass指针找到Person的元类对象;

3. 方法的调用流程:

isa-superclass.png

isa:

  • instance(实例对象)的isa指向class(类对象)
  • class(类对象)的isa指向meta-class(元类对象)
  • meta-class(元类对象)的isa指向基类的meta-class(元类对象)
  • 基类的元类对象的isa指向自己(基类的元类对象)

superclass:

  • class(类对象)的superclass指向父类的class(类对象)
    如果没有父类,superclass指针为nil
  • meta-class(元类)的superclass指向父类的meta-class(元类)
    -基类的meta-class(元类对象)的superclass指向基类的class(类对象)

instance调用对象方法的轨迹
isa找到class,方法不存在,就通过superclass找父类

class调用类方法的轨迹
isa找meta-class,方法不存在,就通过superclass找父类

四. Class结构

class结构 ISA_MASK

struct objc_class

struct objc_class

五:总结

  • 一个NSObject对象占用多少内存?
    系统分配了16个字节给NSObject对象(通过malloc_size函数获得)
    但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)
  • 对象的isa指针指向哪里?
    instance对象的isa指向class对象
    class对象的isa指向meta-class对象
    meta-class对象的isa指向基类的meta-class对象
  • OC的类信息存放在哪里?
    instance对象:存放成员变量的具体值
    类对象中:对象方法、属性、成员变量、协议信息
    元类对象中:类方法

方法的调用轨迹:

  • instance调用对象方法的轨迹
    isa找到class,方法不存在,就通过superclass找父类
  • class调用类方法的轨迹
    isa找meta-class,方法不存在,就通过superclass找父类
上一篇 下一篇

猜你喜欢

热点阅读