objectC 的isa 详解

每个Objective-C对象都有一个隐藏的数据结构,这个数据结构是Objective-C对象的第一个成员变量,它就是isa指针。

在NSObject.h里面:

@interface NSObject <NSObject> {

Class isa  OBJC_ISA_AVAILABILITY;

}

再点开 Class 的定义:

struct objc_class {

Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__

Class super_class                                        OBJC2_UNAVAILABLE;

const char *name                                         OBJC2_UNAVAILABLE;

long version                                             OBJC2_UNAVAILABLE;

long info                                                OBJC2_UNAVAILABLE;

long instance_size                                       OBJC2_UNAVAILABLE;

struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;

struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;

struct objc_cache *cache                                 OBJC2_UNAVAILABLE;

struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;

#endif

}

这一些定义对于懂的人自然懂,不会的人根本看不懂。建议看完下面的例子,再点开参考里面的链接仔细看一遍。

现在我们知道的是,对于我们新建的一个类,都会有一个隐藏的属性isa,可以通过它进行一些访问。

我们现在新建一个类ClassParent,继承于NSObject, 里面有成员方法-(void)selectorP,类方法+(void)ClassSelectorP。

再新建一个类ClassChild,继承于ClassParent,里面有成员方法-(void)selectorC, 类方法+(void)ClassSelectorC。

现在我们新建一个实例ClassChild* child = [ClassChlid new];

当我们调用[child class] 的时候,child就会通过isa指针去找到自己的类对象。

当我们调用[child superclass]的时候,child 就会通过super_class 去找到ClassParent的类对象。

在这里,再普及objc_class 的两种类型:

class     实例对象(child)的isa指向的结构体;

metaclass  类对象(Child,注意大写)的isa指向的一个结构体;

接着,调用[child SelectorC],child通过isa找到实例对象的class,在class(注意看上面 struct objc_class 的定义)的方法列表里面找到SelectorC;

再试着调用[child SelectorP],child通过isa找到实例对象的class,发现class里面并没有这个方法,通过class里面的super_class找到ClassParent的class,在里面的方法列表找到了SelectorP;

再是类方法[Child ClassSelectorC],Child(请注意,这个是类对象)通过isa找到类对象的metaclass(实际上也是class,类型是一样的,只是为了区分而叫不一样的名字),在类对象的metaclass的方法列表里面找到了ClassSelectorC;

再试着调用[Child ClassSelectorP],Child通过isa找到类对象的metaclass,发现metaclass里面并没有这个方法,通过metaclass里面的super_class找到ClassParent的metaclass,在里面的方法列表找到了ClassSelectorP;

这是几个例子基本上已经涵盖了大多数调用的情况。

最后总结下:

child 是一个实例对象,可以有多个,isa指向的class也是有多个的;

Child 是一个类对象,只有一个,isa指向的metaclass只有一个。

最后为了理解class和metaclass的作用,大家可以换位思考一下,如果我们作为runtime的设计者,当开发者新建出来一个实例对象child的时候,我们应该存储child的属性和方法,同时又该如何响应其方法调用,最后还要记录与Parent之间的继承关系。

请注意的是,child实际上只是

参考

http://www.cocoachina.com/ios/20141018/9960.html

http://blog.csdn.net/jasonblog/article/details/7246822

http://blog.csdn.net/totogo2010/article/details/8081253

时间: 2024-10-11 04:54:16

objectC 的isa 详解的相关文章

iOS开发——高级特性&amp;Runtime运行时特性详解

Runtime运行时特性详解 本文详细整理了 Cocoa 的 Runtime 系统的知识,它使得 Objective-C 如虎添翼,具备了灵活的动态特性,使这门古老的语言焕发生机.主要内容如下: 引言 简介 与Runtime交互 Runtime术语 消息 动态方法解析 消息转发 健壮的实例变量(Non Fragile ivars) Objective-C Associated Objects Method Swizzling 总结 引言 曾经觉得Objc特别方便上手,面对着 Cocoa 中大量

windbg命令详解

DLL 该扩展仅在内核模式下使用,即使它是在Ext.dll中的. Windows NT 4.0 Ext.dll Windows 2000 Ext.dll Windows XP和之后 Ext.dll 注释 如果不提供参数,调试器会列出所有进程,以及时间和优先级统计.这和使用!process @#Process 0 作为CommandString值一样. To terminate execution at any point, press CTRL+BREAK (in WinDbg) or CTRL

KVC/KVO原理详解及编程指南

http://blog.csdn.net/wzzvictory/article/details/9674431 2.KVC/KVO实现原理 键值编码和键值观察是根据isa-swizzling技术来实现的,主要依据runtime的强大动态能力.下面的这段话是引自网上的一篇文章: http://blog.csdn.net/kesalin/article/details/8194240 当某个类的对象第一次被观察时,系统就会在运行期动态地创建该类的一个派生类,在这个派生类中重写基类中任何被观察属性的

Linux 查看系统硬件信息(实例详解)

cpu lscpu命令,查看的是cpu的统计信息. [email protected]:~$ lscpu Architecture: i686 #cpu架构 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian #小尾序 CPU(s): 4 #总共有4核 On-line CPU(s) list: 0-3 Thread(s) per core: 1 #每个cpu核,只能支持一个线程,即不支持超线程 Core(s) per socket:

HBase RegionServer详解(未完)

HBase RegionServer详解 RegionServer组件介绍 RegionServer是HBase集群运行在每个工作节点上的服务.它是整个HBase系统的关键所在,一方面它维护了Region的状态,提供了对于Region的管理和服务:另一方面,它与Master交互,参与Master的分布式协调管理. MemStoreFlusher MemStoreFlusher主要功能是将MemStore刷新到文件中,当满足一下条件时会出发MemStore执行flush操作,最小的flush单元是

详解内部类

原文出处:chenssy 可以将一个类的定义放在另一个类的定义内部,这就是内部类. 内部类是一个非常有用的特性但又比较难理解使用的特性(鄙人到现在都没有怎么使用过内部类,对内部类也只是略知一二). 第一次见面 内部类我们从外面看是非常容易理解的,无非就是在一个类的内部在定义一个类. public class OuterClass { private String name ; private int age; public String getName() { return name; } pu

《Linux设备驱动开发详解(第3版)》海量更新总结

本博实时更新<Linux设备驱动开发详解(第3版)>的最新进展. 2015.2.26 几乎完成初稿. [F]是修正或升级:[N]是新增知识点:[D]是删除的内容 第1章 <Linux设备驱动概述及开发环境构建>[D]删除关于LDD6410开发板的介绍[F]更新新的Ubuntu虚拟机[N]添加关于QEMU模拟vexpress板的描述 第2章 <驱动设计的硬件基础> [N]增加关于SoC的介绍:[N]增加关于eFuse的内容:[D]删除ISA总线的内容了:[N]增加关于SP

后缀数组学习笔记【详解|图】

后缀数组学习笔记[详解] 老天,一个后缀数组不知道看了多少天,最后终于还是看懂了啊! 最关键的就是一会儿下标表示排名,一会用数值表示排名绕死人了. 我不知道手跑了多少次才明白过来.其实我也建议初学者手跑几遍,但是一定要注意数组的意义,否则就是无用功. 数组含义: s[ ]:输入的字符串,预处理的时候会在末尾加上一个0 sa[ ]:它的下标就是后缀排名 x[ ] = t[ ]:用来保存第一关键字排名,注意!它的数值是排名.初始时恰好是字符串的ASCII码.字典序嘛! y[ ] = t2[ ]:它的

【转】UML类图与类的关系详解

UML类图与类的关系详解   2011-04-21 来源:网络   在画类图的时候,理清类和类之间的关系是重点.类的关系有泛化(Generalization).实现(Realization).依赖(Dependency)和关联(Association).其中关联又分为一般关联关系和聚合关系(Aggregation),合成关系(Composition).下面我们结合实例理解这些关系. 基本概念 类图(Class Diagram): 类图是面向对象系统建模中最常用和最重要的图,是定义其它图的基础.类