多态、动态类型和动态绑定
多态 能够使来自不同类的对象定义相同的方法
动态类型 能使程序直到执行时才确定对象所属的类。
动态绑定 则能够使程序直到执行时才确定实际要执行的对象方法。
id类型可以用来保存程序中任何类型的对象。
Fraction *f1;
id test = f1;
实际上是一个指针。
Objective-C系统总是跟踪对象所属的类。答案同样存在于动态类型和动态绑定的概念之中,
就是说,先判定对象所属的类,然后在运行时确定需要动态调用的方法,而不是在编译的时候。
id类型在运行时才确定,也就是说无法在编译阶段检查类型错误。
所以,多使用静态类型,编译器尽可能确保变量的用法在程序中保持一致。
但是不要养成滥用这种通用类型的习惯。
还可以将方法名作为参数,进行调用。使用了selector。同样的,无法被编译器检查方法类型和返回类型。
不能对id类型使用点运算符。
使用动态类型调用一个方法,规则:如果在多个类中实现名称相同的方法,
那么每个方法都必须符合各个参数的类型和返回值类型。这样编译器才能为消息表达式生成正确的代码。
NSObject类所支持的一些基本方法,它们用来提出这类问题。
以下表中,class-object 是一个类对象(通常由class方法产生),selector是一个SEL类型的值(通常由@selector指令产生)。
处理动态类型的方法:
方法 | 问题或行为 |
-(BOOL) isKindOfCalss: class-object | 对象是不是class-object或其子类的成员 |
-(BOOL) isMemeberOfCalss: class-object | 对象是不是class-object的成员 |
-(BOOL) respondsToSelector: selector | 对象是否能够响应selector所制定的方法 |
-(BOOL) instanceRespondToSelector: selector | 指定的类实例能否响应selector |
-(BOOL) isSubclassOfCalss: class-object | 对象是否是指定类的子类 |
-(id) performSelector: selector | 应用selecto指定的方法 |
-(id) performSelector: selector withObject: object | 应用selecto指定的方法,传递参数 |
-(id) performSelector: selector withObject: object1 withObject: object2 | 应用selecto指定的方法,传递两个参数 |
通过实例获得类对象
[obj1 class]
查看对象是不是属于它的类对象的成员,虽然这毫无意义。
[obj1 isMemberofClass: [obj1 class]]
生成selector的方法是 @selector (alloc) ,这为名为alloc的方法生成了一个SEL类型的值。
@selector (setTo:over:) , 注意方法中的冒号!
[obj1 instanceRespondToSelector: @selector (setTo:over)] ,测试一下obj1这个实例,能否响应setTo:over: 这个方法。
代码如下
SEL action;
id obj2;
...
action = @selector (draw);
...
obj2 performSelector: action]; //使用selector
也就是之前提到的将方法名放到selector中,可以进行选择执行方法。
还可以使用fowardInvocation:将方法转发给其它对象处理?!
使用try处理异常。
try {
;
}
@catch (NSException *exception) {
;
}
NSException对象,name方法和reason方法。
@finally,无论是否异常,都会执行。
可以在使用@throw抛出异常,也可以在@catch中抛出。
但是抛出异常耗费资源,不建议这么做。更好的做法是返回指定错误类型标识,当然最好先做错误检查,而不是等待抛出异常。
当然可以按照顺序使用多个@catch指令。