OC基础6:多态、动态类型和动态绑定

  "OC基础"这个分类的文章是我在自学Stephen G.Kochan的《Objective-C程序设计第6版》过程中的笔记。

1、关于SEL类型的数据:

(1)、SEL类型的数据包含的是一个方法,使用@selector()把一个方法名包含在括号内,就可以取到这个方法,然后可以以这个数据作为参数去调用一些方法;

(2)、一般用于那些处理动态类型的方法中,比如有方法-(BOOL)respondToSelector: selector,这个方法是判断某个类能否响应某个方法。比如有实例a,有方法b,这个方法的应用如下:

[a respondToSelector: @selector(b)];

当然它的返回值是BOOL类型,需要用来做判断,这里不做演示。这个例子可以说明@selector是怎么使用的;

(3)、对于放在@selector括号里面的方法名后面的分号:如果方法没有参数,那么括号里不能写上分号,比如:@selector(b),如果方法有参数,则全部分号都必须写上,比如:@selector(add:and:)或者:@selector(b:);

(4)、对于所有的类,只要方法名是一样的,产生的selector都是一样的。

2、使不同的类共享相同的方法名称的能力成为多态。假如Fraction类和Complex类都包含了add:方法,并且分别有实例f1、f2、f3、c1、c2、c3,那么当执行以下语句的时候:

f1 = [f2 add: f2];

c1 = [c2 add: c3];

编译器会自动匹配Fraction类和Complex类各自的add:方法,这就是多态。

3、id类型是一种通用的对象类型,可以用来存储任何类的对象。同时需要注意,在声明类的实例的时候是要用到“*”号的(比如“Fraction *f1;”),而声明一个id类型的对象时,不需要用到“*”号(比如“id dataValue;”)。

4、关于动态绑定:在编译的时候无法确定对象的类型,直到在运行的时候才能确定,进而确定要调用的方法。比如使用id类型定义一个对象,然后使用这个对象调用方法,那么编译的时候编译器无法确定这个对象的类型,直到运行的时候才能正确匹配。

5、动态绑定也会带来一些问题,比如A类不包含方法b:,那么以下语句:

id a = [[A alloc] init];

[a b];

编译器无法检查出错误,因为在动态绑定之前,编译器并不知道a的类型,所以也无法判断a使用b:方法是否正确。

6、id变量不能使用点运算符,编译器会报错。

7、编译器在编译的时候不会检查id类型的具体类型的!

8、当使用动态类型的对象作为参数来调用方法的时候,如果调用了不同的类相同名称的方法,必须保证:每个方法需求的参数类型和返回值类型必须匹配。即是动态类型的对象在运行时被赋予了确定的类型时,这个类型必须能够匹配代码中调用的方法所需要的类型。比如dataValue1和dataValue2是id类型,有如下代码:

result = [dataValue1 add: dataValue2];

那么编译器仍然会生成代码,它是通过假设来处理返回值的。这时候如果在运行时dataValue1和dataValue2被赋予的类型和add:方法不匹配,那么就会出现错误。

9、关于对象的静态类型和动态类型:

静态类型的对象即是对对象的类型已经进行过显式声明的,比如“Fraction *f1;”,它的类型是确定的、不变的、静态的;动态类型的对象即是对象的类型并未在一开始就确定(但是可能会先有声明),比如“id f1;”,它的类型是未定的、可变的、动态的。

10、类名并不等同于类,比如在程序中,Fraction这个名字并不等同于Fraction类,如果需要使用到Fraction的类,需要使用以下代码:

[Fraction class];

那么就能取到Fraction的类。这种做法的作用是,有时可以做如下判断:

if ([a clsaa] == [b class])

可以知道a和b是不是属于同一个类;

11、关于@try块处理异常,一般的处理模板如下:

@try {

[f noSuchMethod];

}

@catch (NSException *exception) {

}

12、另外如果出现@finally块的话,无论@try块内是否会抛出异常,@finally块都会执行

上一篇:JAVA 静态方法和实例方法的区别 (图表)


下一篇:Linux进程间通信:IPC对象——信号灯集详解