object c中的多态
2016-06-02 09:54
399 查看
1,何为多态:不同对象可以访问相同方法的能力或现象。
2,多态的优势:不同的类对象可以使用习惯的调用方式;简化了编程接口;实现类和实例的接口隔离。
动态绑定,多态,在C++中主要是指基类指针,调用继承类所实现的虚方法。
在object C中,有比较新的展现形式。
(一)消息机制
oc中的消息机制就是一个动态绑定的过程,
每个类实例的第一个字段isa指针,指向类的结构体定义,里面有函数列表,缓存函数列表,协议列表,类名,实例参数列表,实例大小.....。
消息调用过程:编译过程中会在函数调用的代码处添加,obj_msgSend:函数调用;程序运行期,此函数完成动态绑定的所有过程。按照编译期改为obj_msgSend写时,填入的调用类,被调用者类,和他们的函数列表,找到对应的IMP即函数指针,完成函数调用。
该消息函数做了动态绑定所需要的一切:
它首先找到选标所对应的方法实现。因为不同的类对同一方法可能会有不同的实现,所以找到的方法实现依赖于消息接收者的类型。
然后将消息接收者对象(指向消息接收者对象的指针)以及方法中指定的参数传给找到的方法实现。
最后,将方法实现的返回值作为该函数的返回值返回。
(二)delegate,protocol配合的观察者模式,是oc中多态的最常见运用方式
观察者注册,符合某种protocol的id实例指针,
当被观察者认为条件满足是,通过实例指针id,去调用protocol规定的同一种方法即可。
不论多少个观察者,只要都实现了protocol规定的方法,都可以完成调用,
Object-C难以理解的一些概念
1.object-c 怎么实现多态
答:多态是在runtime里面实现的,在编译的时候,compiler把所有class的定义都存放在class 实例对象里面,class实例对象包含了class的父class 实例对象的地址,class方法的select id和地址, class变量的偏移等。所有new出来的object都是从NSObject继承过来的,所以所有对象都自动包含了一个isa的指针,这个指针在调用alloc为object分配地址的时候被指向class对象的地址,在运行的时候,我们调用class
方法是通过给object发送消息
[myobj method]这样的形式,但编译器会把这句话替换成
id objc_msgSend(id theReceiver, SEL theSelector, ...)
第一个参数就是myobj,第二个参数是“method”这个字符串经过编码以后得到的唯一值,apple在runtime的时候查找method都是用
selector来做的,这样效率会比字符串比较的效率要高。
objc_msgSend这个函数的执行过程大概就是,从thereceiver(也就是myobj)里面得到isa的地址,这个地址指向前面讲到的
编译器生成的class的object实例的地址(具体的结构请参考The Objective-C Programming Language),然后比较方法的selector
如果找到了,就知道了method的地址,就直接调用了。
2.对象的method是怎么访问对象 变量的?
答:在编译期间,编译器可以知道指定class的所有继承关系,所以它也知道要生成的object包含的所有变量(包含了父类的)。这样
它就能算出所有变量相对于oject的首地址的偏移。在运行的时候,我们这样调用object 的方法:
[myobj method];
实际上编译器会隐含的把myobj的地址传递给method,所谓第一个参数(这个就是隐含参数的概念,请参考apple object c的文档)
这样知道了object的首地址和变量的偏移,也就知道了变量的地址。
3。self和super关键字是怎么实现的?
答:这个是面对对象语言容易出错的地方,必须要理解这两个关键字的实现原理才能掌握他们的正确使用方法,请参考apple
object c文档中举的例子来了解为什么非常容易出错。
上面我们提到了method在被调用的时候,会被传入隐含参数,第一个隐含参数就是object的地址,self实际上在编译期间被替换成了
ojbect的地址,所以堆self发送的消息都是根标准流程一样通过isa链找到method来执行。
super就不一样,super关键字被编译器替换成了
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
其中objc_super的结构是
struct objc_super
{
id receiver;
Class class;
};
注意到
objc_msgSendSuper
和
id objc_msgSend(id theReceiver, SEL theSelector, ...)的区别,多了一个Class class;
class实际上就指向了找到当前method的class 对象的实例。
所以在objc_msgSendSuper中查找方法是从参数class指向的class 实例对象的isa开始查找的,而不是从theReceiver也就是myobj
这个对象的isa开始查找的
2,多态的优势:不同的类对象可以使用习惯的调用方式;简化了编程接口;实现类和实例的接口隔离。
动态绑定,多态,在C++中主要是指基类指针,调用继承类所实现的虚方法。
在object C中,有比较新的展现形式。
(一)消息机制
oc中的消息机制就是一个动态绑定的过程,
每个类实例的第一个字段isa指针,指向类的结构体定义,里面有函数列表,缓存函数列表,协议列表,类名,实例参数列表,实例大小.....。
消息调用过程:编译过程中会在函数调用的代码处添加,obj_msgSend:函数调用;程序运行期,此函数完成动态绑定的所有过程。按照编译期改为obj_msgSend写时,填入的调用类,被调用者类,和他们的函数列表,找到对应的IMP即函数指针,完成函数调用。
objc_msgSend(receiver, selector, arg1, arg2, ...)
该消息函数做了动态绑定所需要的一切:
它首先找到选标所对应的方法实现。因为不同的类对同一方法可能会有不同的实现,所以找到的方法实现依赖于消息接收者的类型。
然后将消息接收者对象(指向消息接收者对象的指针)以及方法中指定的参数传给找到的方法实现。
最后,将方法实现的返回值作为该函数的返回值返回。
(二)delegate,protocol配合的观察者模式,是oc中多态的最常见运用方式
观察者注册,符合某种protocol的id实例指针,
当被观察者认为条件满足是,通过实例指针id,去调用protocol规定的同一种方法即可。
不论多少个观察者,只要都实现了protocol规定的方法,都可以完成调用,
Object-C难以理解的一些概念
1.object-c 怎么实现多态
答:多态是在runtime里面实现的,在编译的时候,compiler把所有class的定义都存放在class 实例对象里面,class实例对象包含了class的父class 实例对象的地址,class方法的select id和地址, class变量的偏移等。所有new出来的object都是从NSObject继承过来的,所以所有对象都自动包含了一个isa的指针,这个指针在调用alloc为object分配地址的时候被指向class对象的地址,在运行的时候,我们调用class
方法是通过给object发送消息
[myobj method]这样的形式,但编译器会把这句话替换成
id objc_msgSend(id theReceiver, SEL theSelector, ...)
第一个参数就是myobj,第二个参数是“method”这个字符串经过编码以后得到的唯一值,apple在runtime的时候查找method都是用
selector来做的,这样效率会比字符串比较的效率要高。
objc_msgSend这个函数的执行过程大概就是,从thereceiver(也就是myobj)里面得到isa的地址,这个地址指向前面讲到的
编译器生成的class的object实例的地址(具体的结构请参考The Objective-C Programming Language),然后比较方法的selector
如果找到了,就知道了method的地址,就直接调用了。
2.对象的method是怎么访问对象 变量的?
答:在编译期间,编译器可以知道指定class的所有继承关系,所以它也知道要生成的object包含的所有变量(包含了父类的)。这样
它就能算出所有变量相对于oject的首地址的偏移。在运行的时候,我们这样调用object 的方法:
[myobj method];
实际上编译器会隐含的把myobj的地址传递给method,所谓第一个参数(这个就是隐含参数的概念,请参考apple object c的文档)
这样知道了object的首地址和变量的偏移,也就知道了变量的地址。
3。self和super关键字是怎么实现的?
答:这个是面对对象语言容易出错的地方,必须要理解这两个关键字的实现原理才能掌握他们的正确使用方法,请参考apple
object c文档中举的例子来了解为什么非常容易出错。
上面我们提到了method在被调用的时候,会被传入隐含参数,第一个隐含参数就是object的地址,self实际上在编译期间被替换成了
ojbect的地址,所以堆self发送的消息都是根标准流程一样通过isa链找到method来执行。
super就不一样,super关键字被编译器替换成了
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
其中objc_super的结构是
struct objc_super
{
id receiver;
Class class;
};
注意到
objc_msgSendSuper
和
id objc_msgSend(id theReceiver, SEL theSelector, ...)的区别,多了一个Class class;
class实际上就指向了找到当前method的class 对象的实例。
所以在objc_msgSendSuper中查找方法是从参数class指向的class 实例对象的isa开始查找的,而不是从theReceiver也就是myobj
这个对象的isa开始查找的
相关文章推荐
- 关于ios object-c 类别-分类 category 的静态方法与私有变量,协议 protocol 
- 使用Objective-C的+(void)initialize初始化static变量
- objectForKey与valueForKey在NSDictionary中的差异
- IOS——objc_setAssociatedObject关联的使用
- Objective-C中的浅拷贝和深拷贝
- Objective-C 中 +load 与 +initialize
- Objective-C 神在细节之中
- 鸟哥Java学习之Object类-面向对象
- ios中object c纯代码开发屏幕适配处理方法
- READING NOTE: Inside-Outside Net: Detecting Objects in Context with Skip Pooling and Recurrent Neura
- List<Map<String,Object>>使用Java代码遍历以获取String,Object的值
- JAVA Class vs Object vs Instance
- 简单封装Jackson,实现JSON String到Java Object的Mapper.
- 属性动画之ObjectAnimator
- count the number of objects--物体计数
- hibernate的3中查询举例——返回对象或转化对象、返回Object
- Objective C类方法load和initialize的区别
- 自己开发的一个Xcode插件
- JSONObject和JSONArray使用
- 使用Objective-C创建UUID的代码