内容简介:我们先来解释一下苹果官方给开发者提供的这张图例如我们创建个自己的类Q : Instance(类对象),class(类),meta(即meta-class元类) 里面各存着这么
我们先来解释一下苹果官方给开发者提供的这张图
例如我们创建个自己的类 LWPerson *person = [[LWPerson alloc] init]; 每个类都有自己的 isa ,它指向对应的了 [LWPerson Class] , [LWPerson Class] 也有自己的 isa ,它则指向对应的元类 meta ;这里解释一下两个问题
Q : Instance(类对象),class(类),meta(即meta-class元类) 里面各存着这么
A : Instance 存着一个 isa 指向 class ,还存着自己的成员变量; class 里存有 isa , superclass ,属性、对象方法、协议、成员变量等; meta 里存在 isa,superclass ,类方法等;如图(图片引用自李明杰老师)
isa
要这样指来指去,这样有什么好处
A : 例如这段代码
LWPerson *person = [[LWPerson alloc] init]; person.age = 20; persom.height = 180; [person sing]; [person dance]; [person rap]; 复制代码
其中 age 和 height 都是每个 LWPerson 私有的,每创建一个 LWPerson 都可能不一样,但是 sing , dance , rap 方法是每一个 LWPerson 共有。所以当创建 LWPerson 对象后,只需 isa 和成员变量,所有的方法都放在 LWPerson 的类里,对象通过 isa 找到对应类的的方法,这样可以大大的节省 LWPerson 对象所占用的内存。这里 LWPerson 类的 isa 指向 LWPerson 的元类,类方法就存在元类里,也很好的解释了一般情况下 类方法为什么不能使本身的成员变量,因为存在类对象上;
接回之前的继续说:每个类都存有一个 superclass 指针,这很好理解,子类如果找不到对应的方法,便会顺着 superclass 指针找到对应的父类。 meta 的也一样本身没有的类方法也会去寻找父类的类方法,这样一直一级一级往上传,一直传到 Root Class , Root Class 的元类比较特殊,苹果设计它的 isa 指向自己, superclass 指向 Root Class ,如果 Root Class 也找不到方法,就会报一个我们很熟悉的错误 unrecognized selector sent to instance 0x600001a3a5b0
可能上面说的比较多比较乱,我们可以举个栗子再捋一次 首先,我们创建个类 LWPerson 继承于 NSObject 。
LWPerson *person = [[LWPerson alloc] init]; 复制代码
在创建 LWPerson 的时候,我们用的 [LWPerson alloc] 本质就是 LWPerson 类通过 isa 去 meta 里找类方法,但是找不到!就再通过 meta 的 superclass 找到它的父 meta 即 NSObject 的 meta , NSObject 的类方我们很容易就可以找到 alloc 。 init 也是同理,我们在 [LWPerson alloc] 后,它实际上返回的是一个 LWPerson 的对象,它本身也没有 init 对象方法,所以找它的父类 NSObject 的对象方法 init
我们也可以在 LWPerson.h 中声明一个 -(void)sing 方法,但不写实现,这样 person 对象就会去 LWPerson 的类里找 sing 方法,但没实现 sing 方法,就会顺着 superclass 去 NSObject 到对象方法,但 NSObject 也没有 sing 方法,所以继续往上找到了 Root Class ,但 Root Class 也没有 sing 方法,所以指向 nil ,系统报错 unrecognized selector sent to instance 。
这就是方法系统调用的过程,当然还有不少更底层更细致的流程,篇幅原因就下次再细聊了
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Base64 编码/解码
Base64 编码/解码
XML 在线格式化
在线 XML 格式化压缩工具