Object-C难以理解的一些概念
2012-03-21 16:50
344 查看
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开始查找的.
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开始查找的.
相关文章推荐
- Object-C难以理解的一些概念
- object-c难以理解的一些概念
- 从别人写的 Object-C 中 Singleton (单例) 模式 中的一些理解
- 关于对于spring当中一些基础概念的理解
- 一张图更好的帮助你理解css中的一些概念
- 操作系统的一些概念理解
- java --- 入门时的一些基本概念的理解(j2ee,j2se,j2me,jdk,jre,jvm,跨平台)
- java中一些概念理解
- 使用针式PKM的必须理解的一些概念
- SSH网上商城初步——一些概念的理解
- 理解嵌入式开发中的一些硬件相关的概念
- 关于sd卡中一些概念的理解
- OOP中一些概念理解
- FPGA中一些概念自己的理解
- 读《重构-改善既有代码的设计》的一些简单的概念和理解
- 搞清楚局部和全部,搞清楚逻辑和物理,搞清楚这些对于理解一些组件的概念是非常有意义的:
- 从别人写的 Object-C 中 Singleton (单例) 模式 中的一些理解
- OC一些概念上的理解
- Java中一些概念理解
- .NET中一些概念理解