zoukankan      html  css  js  c++  java
  • iOS中OC对象模型的理论知识过一遍

    以前学习化学知识的时候,有一句经典的话就是:“结构决定性质”。

    这句话在软件开发中依然适用,不管是日常的业务开发工作,还是想探索下OC的底层原理,都离不开结构的限制。

    本文是记录OC对象模型的结构设计。

    ==第一部分==

    OC是一门面向对象的编程语言,每一个对象都是一个类的实例。在OC语言的内部,每一个对象都有一个名为isa的指针,指向该对象的类。每一个类描述了一系列它的实例的特点,包括成员变量的列表、成员函数的列表等。每一个对象都可以接受消息,而对象能够接受的消息列表保存在它所对应的类中。

    按照面向对象语言OOP的设计原则,所有的事物都应该是对象,严格来说,OC并没有完全做到这一点,因为它有像int、double这样的简单变量类型,而类似Ruby一类的语言,连int变量也是对象。

    因为类也是一个对象,所以它也必须是另一个类的实例,这个类就是元类(metaclass)。元类保存了类方法的列表。当一个类方法被调用时,元类会首先查找它本身是否有该类方法的实现,如果没有,则该元类会向它的父类查找该方法,这样可以一直找到继承链的源头。

    元类也是一个对象,那么元类的isa指针又指向哪里呢?为了设计上的完整,所有的元类的isa都会指向一个根元类(root metaclass)。根元类本身的isa指针指向自己,这样就形成了一个闭环。前面所提到的,“一个对象能够接受的消息列表是保存在它所对应的类中的”。在实际编程中,我们几乎不会遇到向元类发消息的情况,因此元类的isa指针很少在实际中用到。不过,设计“根元类”是为了保证面向对象概念在OC语言中的完整,即语言中的所有事物都是对象,都有isa指针

    根据isa指针这条线路,基本可以得出以下图示:

     

    如果把类的实例看成是一个C语言的结构体struct,那么上面提到的isa指针就是这个结构体的第一个成员变量,而类的其他成员变量依次排列在结构体中,其他的成员变量包括类本身的成员变量,和从父类链继承过来的成员变量。因为对象在内存中的排布可以看成是一个结构体,该结构体的大小并不能动态变化,所以无法在运行时动态地给对象增加成员变量。这就是为什么分类category只可为对象增加成员方法,却不能增加成员变量的原因。而动态更改isa指针的应用场景之一就是KVO的实现

    虽然通过objc_setAssociatedObject和objc_getAssociatedObject方法可以变相地给对象增加成员变量,但由于实现机制不一样,所以并不是真正改变了对象的内存结构。

    正是因为isa指针和method指针的类型是指针,多以可以动态地修改指针的值,从而做到对isa sizzling和method swizzling的支持

    与实例对象中的成员变量不一样,对象的方法定义都保存在类的可变区域中。OC 2.0 并未在头文件中将实现暴露出来,但在OC 1.0 中,我们可以看到方法的定义列表是一个名为methodLists的指针的指针。通过修改该指针指向的指针的值,就可以动态地为某一个类增加成员方法。这也是分类category实现的原理

    在OC的高级语法中,比如使用runtime运行时更改系统方法的定义、KVO的实现、消息的转播等等,都是对isa指针和method指针的利用。当然,runtime运行时的作用远远不止这些应用场景。

    ==第二部分==

    上面提到的类、元类、根元类,加上根类NSObject是有继承关系的。由于类方法的定义时保存在元类中,而方法调用的规则是,如果该类没有一个方法的实现,则向它的父类继续查找。所以,为了保证父类的类方法在子类中可以被调用,所有子类的元类都会继承父类的元类,换而言之,类对象和元类对象有着同样的继承关系。

    根据继承这条关系线路,可以得到下面的图示:

    ==第三部分==

    如果想进一步探索底层的一些结构,可以在Xcode中按快捷键 Shift + Cmd + O,然后输入“NSObject”、“objc.h”、“runtime.h”。

    在调试时,可以运行到“断点”处后,在Console中输入(比如:p *child)进行对象模型结构的查看。

     

  • 相关阅读:
    WCF 第十三章 可编程站点 为站点创建操作
    WCF 第十三章 可编程站点 所有都与URI相关
    WCF 第十二章 对等网 使用自定义绑定实现消息定向
    WCF 第十三章 可编程站点 使用WebOperationContext
    Using App.Config for user defined runtime parameters
    WCF 第十三章 可编程站点
    WCF 第十三章 可编程站点 使用AJAX和JSON进行网页编程
    WCF 第十二章 总结
    WCF 第十三章 可编程站点 使用WebGet和WebInvoke
    WCF 第十三章 可编程站点 URI和UriTemplates
  • 原文地址:https://www.cnblogs.com/cchHers/p/14910105.html
Copyright © 2011-2022 走看看