首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > 移动开发 >

Objective-C学习札记11:多态和动态类型

2013-03-06 
Objective-C学习笔记11:多态和动态类型接上文多态是一个典型的面向对象概念。Objective-C中的多态可以使得

Objective-C学习笔记11:多态和动态类型
    接上文
    多态是一个典型的面向对象概念。Objective-C中的多态可以使得来自不同类的对象定义同名方法。
    我们来看下面的示例,分数类Fraction我们已经多次涉及到了,我们来回顾一下我们分数类的定义:


    我们分别定义了两个分数和两个复数,分别对其使用add方法进行相加,然后使用print方法进行打印。编译运行这个程序,我们得到如下的结果:




    那么可以看到,我们分别得到了正确的结果。在Objective-C中不同的类使用相同的方法名的能力称为多态。那么我们在开发一组类时,它们可以使用相同的方法名而每个类又有不同的实现代码。那么多态还允许你创建心类时,这些新类也使用相同的方法名。
    我们继续来深入说明。在Objective-C中有一种数据类型比较特殊,就是id类型。id表示一种通用的对象类型,也就是说id可以用来存储任何类的对象。那么我们使用这种方式来存储不同类型的对象时,在程序运行期间,这种数据类型的优势就体现出来了,我们修改上面的主函数,使用id类型来看一下:

    和之前的程序相比,这里我们定义了id类型的result变量,并且删除了分数类和复数类各自的result对象,统一使用id类型的变量作为替代,那么运行程序,我们先来看一下结果:




    可以看到,程序依然正确运行,我们得到了想要的结果。这里我们将result定义成id类型,那么它就可以表示任何类型的对象,请特别注意,这个声明不是指针类型,不加星号。那么在做分数运算时,result首先被赋值为Fraction类型,这是Objective-C程序运行时的动态类型和动态绑定机制,这种动态机制就是在运行时先判断对象所属的类,然后调用对应的方法,而在编译时是不检查的。依照这个理论,那么在执行复数类的print时,result对象已经赋值为了复数类型的结果,那么自然打印复数。
    想想我们之前的矩形和正方形的例子,如果加入了draw方法,那么对于矩形和正方形的实现肯定是不同的。而若在程序中我们可能还会有圆形,三角形等图案,那么若定义了id类型的shape变量,它就可以表示任何图形了,在运行时动态确定结果,动态选择要执行的所属类的draw方法就可以得到不同的图案了,这就是动态类型和动态绑定的实现。
    看下面的代码段:



    我们可以看到通过class方法我们可以获取当前对象的类型,使用类名来调用通常也是为了返回这个类型的对象,他们都是Class类型的对象。那么我们知道class方法的用处后就可以用于判断了,比如下面的代码:



    下面介绍@selector指令,该指令用于一个方法名,比如@selector (alloc),它的返回值是SEL类型,这个指令所获取的SEL类型结果也是用于动态类型的一些方法的,这里我们仅仅有个感性认识即可,那么看下面的代码:



    那么在后面处理动态类型的方法中,我们会看到@selector指令的具体用途。参考下面的程序:



    我们逐行来解释一下这个程序,isMemberOfClass : class方法用于判断对象是不是class的成员,返回值为BOOL类型,那么这里我们使用三目运算符来获取BOOL表达式的结果,NSString也是id类型的一种,那么我们使用%@来表示。很显然square对象是Square类的一个成员,而不是Rectangle类和NSObject类的成员。
    isKindOfClass: class方法用于判断对象是不是class类或其子类的成员。显然square对象是Square类的成员,是Rectangle类和NSObject类的子类成员。
    respondsToSelector : selector方法用于判断对象是否可以响应@selector提供的方法,那么直接看上面的结果即可,不用多说了。instanceRespondToSelector : selector方法用于判断指定的实例能否响应@selector提供的方法,那么直接看结果就行了。
    这些方法我们仅仅有个感性认识即可,等后续内容使用到了再做深入了解。
    我们知道运用动态类型时在程序执行过程中可能会出现异常,那么如何来处理异常呢?Objective-C中引入@try块儿来处理异常,异常处理在@catch块中进行。我们来看下面的代码:



    之后我们修改代码,不会出现异常时是这样的情况:



    可以看到@finally块中的语句无论异常是否发生,都会执行。所以它常用来进行连接的关闭等操作。如果想主动抛异常,还可以使用@throw指令来进行,这就是更高级内容了,暂时先不涉及。因为异常处理的开销很大,特别是移动设备对资源占用很敏感,所以非必要,请不要使用异常处理。
    接下文

热点排行