objective-c 语法 细节(一)

本文深入探讨Objective-C中的动态绑定机制,包括消息传递过程、方法选择器、SEL类型、方法覆盖与重写、组合与属性变量使用,以及运行时创建新类的步骤。详细解析Objective-C如何在编译与运行时灵活地处理方法调用与对象状态。

三、动态绑定

1. objective-c,一个对象内否调用指定的方法不是由编译器决定而是由运行时决定,这被称作是方法的动态绑定

    

2. objective-c,对象不调用方法,而是接收消息,消息表达式为: [reciver message];运行时系统首先确定接收者的类型(动态类型识别),后根据消息名在类的方法列表里选择相依的方法执行,以在源代码里消息也称为选择器(selector)

3. 消息函数的作用:

首先通过第一个参数的receiver,找到它的isa指针,后在isa 指向的Class 对象中使用第二个参数selector 找方法;

如果没有找到,就使用当前Class对象中的新的isa 指针到上一级的父类的Class 对象中查找;

当找到方法后,再依据receiver的中的self 指针找到当前的对象,调用当前对象的具体实现的方法(IMP),然后传递参数,调用实现方法。

假如一直找到NSObjectClass 对象,也没有找到你调用的方法,就会报告不能识别发送消息的错误。



Objective-C在编译的时候,会根据方法的名字 (包括参数序列),生成一个用来区分这个方法的唯一的一个标示(ID),这个标示(ID)就是SEL类型的,在运行时候是通过方法的标示来查找方法的。只要方法的名字(包括参数序列)相同,那么它们的 ID都是相同的。可以通过@select()指示符获得方法的标示。SEL mydraw =@select(draw)

NSSelectorFromString(NSString*);根据方法名得到方法标识

(NSString*)NSStringFromSelector(SEL);得到SEL类型的方法名



Objetive-C中的Method结构

struct objc_method{

SEL method_name;//方法名

char *method_types; //方法地址

IMP method_imp; //方法地址(IMP)

};typedefobjc_method Method;



在运行时创建一个新类,只需要3:

1、为 class pair分配存储空间 ,使用objc_allocateClassPair函数

2、增加需要的方法使用class_addMethod函数,增加实例变量用class_addIvar

3、用objc_registerClassPair函数注册这个类,以便它能被别人使用。

注意:使用这些函数请引#import <objc/runtime.h>


5.子类继承父类所有的方法。如果子类于父类同名方法,参数个数、类型和返回值一致,那么子类方法会覆盖父类方法,相当于C++中的虚函数进行重写override.



6.NSObject类实现了alloc,delloc,release,init方法.

alloc不需要在子类中重载

dealloc中释放在初始化中申请的内存,一般可能重载

release使对象的引用计数-1,当对象的引用计数为0时,系统自动调用对象的delloc方法释放对象的内存,此方法一般不需要重载。

            init一般需要重载,初始化对象。


二、继承下的消息传递

继承下消息传递规则:先本类再父类,若一直到根类中都没有找到相应消息则报错。



三、组合

1.概念:如果一个类的实例变量是另外一个类的对象,则这两个类是“hasa”关系,表达的是整体-部分关系,但再objective-C中这样的实例变量只能是对象指针,不能是对象。这种方式叫做组合。

2.特别注意:注意组合方式下对象指针作为实例变量的initset方法,一般会重写dealloc方法释放内存。一定要遵循内存管理机制,防止内存泄漏。 ????



方法重写

       Objective-c中,子类可继承父类中的方法,而不需要重新编写相同的方法,直接可以使用父类的方法。

       但有时我们不想使用使用父类方法,而是想作一定的修改,怎么办呢?只要将子类中书写一个与父类具有相同的方法名、返回类型和参数,就可以将将父类的方法覆盖重写。比较简单。

方法重载

       Objective-c中,方法是不能重载的。也就是说我们不能在类中定义这样的两个方法:它们的名子相同,参数个数相同,参数类型不同,不同的返回值类型。否则Xcode会报错。


   每个Object-C对象都隐藏着一个数据结构,它的第一个成员变量或者说实例变量是"isa"指针。 isa指针指向的是对象的类,这个类也是一个对象,有自己的权限,是根据类的定义编译而来的。类对象负责维护一个方法调度表,该表实际上是由指向类方法的指针组成的。类对象中还保留一个超类的指针,该指针又有自己的方法调度表和超类。 isa指针对消息分发机制和cocoa对象的动态能力很重要。


  oc的运行环境(runtime library)完全是由c编写的。因此任何一个消息的派发,最终都会转化为几个c函数的调用。这样,occ语言可以完全的兼容了。



3)属性和变量的用法

    属性是用self.object,通过getter方法来调用的,可以在类外使用。而变量是通过_object来调用,只能在该类对应的implementation中使用,在类外不能使用。

    下面看一下两种赋值操作:

   

[plain] view plaincopy


  1. self.object = [[MyObject alloc] init];  
  2. object = [[MyObject alloc] init];  

    第一种的方式和@propertynonamticretain)有关,实际上是通过调用setter方法setObject来实现赋值的。第二种方式是简单的指针赋值,没有调用setter方法。


   下面是retainCount的变化:


[plain] view plaincopy


  1. MyObject *tmp = [[MyObject alloc] init];  
  2. self.object = tmp;  //retainCount = 2  
  3. [tmp release];  //retainCount = 1  
  4. _object = [[MyObject alloc] init];  //retainCount = 1  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值