郝萌主倾心贡献。尊重作者的劳动成果,请勿转载。

假设文章对您有所帮助,欢迎给作者捐赠。支持郝萌主。捐赠数额任意,重在心意^_^

我要捐赠: 点击捐赠

Cocos2d-X源代码下载:点我传送


多态这个其他语言也有。

动态类型有类似的。但不全然同样。

动态绑定别的语言也有类似。但没有objective-c用的这么多。

多态可以使来自不同类的对象定义同样名称的方法。

动态类型能使程序直到运行时才确定对象所属的类。

动态绑定则能使程序直到运行时才确定实际要调用的对象方法。

多态性是指在父类中定义的成员变量和方法被子类继承之后, 能够具有不同的数据类型或表现出不同的行为。

这使得同一个变量和方法在父类及其各个子类中具有不同的表现形式。

简单点说:同样的名称。不同的类,系统总是携带有关“一个对象属于哪个类”这种信息。

该信息能使系统在执行时做出这些关键性的决定,而不是在编译时。

这样的使不同的类共享同样方法名称的能力就称为多态。

我们通过一个样例理解什么是多态:

比如: “几何图形” 类的“画图” 方法, 在它的子类“椭圆形” 和“三角形” 中也都有“画图” 的方法,
可是“画图” 方法功能都不同。


几何图形类图

Graphics(几何图形) 类是Ellipse(椭圆形) 类和Triangle(三角形) 类的父类, 
Ellipse和Triangle重写了onDraw方法。



Graphics.h文件
Graphics类在h文件里定义onDraw。 Graphics类应该无法实现这

个onDraw。 这是由于在几何图形中是无法知道要绘制的是椭

圆形和三角形, 这种方法应该是类似Java中的抽象方法, 或者是

C++中的虚方法。 

@interface Graphics : NSObject {

}

-(void) onDraw;

@end
Ellipse类的h和m文件
#import <Foundation/Foundation.h>
#import "Graphics.h" @interface Ellipse : Graphics { } @end
#import "Ellipse.h"

@implementation Ellipse

-(void)onDraw {
NSLog(@"绘制椭圆形");
} @end
Triangle类的h和m文件
#import <Foundation/Foundation.h>
#import "Graphics.h" @interface Triangle : Graphics { } @end
#import "Triangle.h"

@implementation Triangle

-(void)onDraw {
NSLog(@"绘制三角形");
} @end
调用的main函数
#import <Foundation/Foundation.h>
#import "Graphics.h"
#import "Ellipse.h"
#import "Triangle.h" int main (int argc, const char * argv[]) { Graphics *graphics;
graphics = [[Ellipse alloc] init];
[graphics onDraw];
[graphics release]; graphics = [[Triangle alloc] init];
[graphics onDraw];
[graphics release]; return 0;
}

执行结果:

绘制椭圆形

绘制三角形

动态类型和动态绑定
id 是泛类型 (generic data type), 能够用来存放各种类型的对象, 
使用 id 也就是使用“动态类型”。 

上面的样例改写下:
int main (int argc, const char * argv[]) {

id graphics;

graphics = [[Ellipse alloc] init];

[graphics onDraw];

[graphics release];

graphics = [[Triangle alloc] init];

[graphics onDraw];

[graphics release];

return 0;

}


把Graphics *改成id类型。 程序执行的结果没有不论什么影响。

因为动态类型的关系,id 在运行时, 
Objective-C 的运行环境会找出该 id 所代表的原来类型。 
所以根本没有所谓的转型。 
id 并非自己主动的转换成 Ellipse和 Triangle的父类,而是在运行期间, 
由运行环境辨认出 id 实际代表的类型为Ellipse还是Triangle。 
因此在这个样例中id 与Graphics没有不论什么关系。

务必注意,声明中并没有使用星号。

我们再举一个样例来说明动态的概念:
矢量和标量是数学和物理学应用中经经常使用到的两个概念;
矢量” 即有方向和大小的量, 如物理学中的“力” 。 
标量为没有方向仅仅有大小量, 如物理学中的“功”。

以下从程序的角度来实现这两个概念。
先定义两个类: “矢量” 和“标量” 类。


Vector.h文件
#import <Foundation/Foundation.h>

@interface Vector : NSObject {
double vec1;
double vec2;
} @property double vec1,vec2;
-(void)print;
-(void)setVec1:(double)v1 andVec2:(double) v2;
-(Vector *)add:(Vector *)v; @end
Vector.m文件
#import "Vector.h"

@implementation Vector
@synthesize vec1,vec2;
-(void) setVec1:(double) v1 andVec2:(double)v2 {
vec1 = v1;
vec2 = v2;
}
-(Vector *)add:(Vector *)v {
Vector *result = [[Vector alloc] init];
[result setVec1:vec1 + [v vec1] andVec2: vec2 + [v vec2]];
return result;
} -(void)print {
NSLog(@"%g, %g",vec1,vec2);
} @end
Scalar.h文件
#import <Foundation/Foundation.h>

@interface Scalar : NSObject {
double scal;
}
@property double scal;
-(void)print;
-(void)setScal:(double)sval;
-(Scalar *)add:(Scalar *)s; @end
Scalar.m文件
#import "Scalar.h"

@implementation Scalar

@synthesize scal;

-(void)print {
NSLog(@"%g", scal);
} -(void)setScal:(double)sval {
scal = sval;
} -(Scalar *)add:(Scalar *)s {
Scalar *result = [[Scalar alloc] init];
[result setScal:scal + [s scal]];
return result;
}
调用的main函数
#import <Foundation/Foundation.h>

#import "Vector.h"
#import "Scalar.h" int main (int argc, const char * argv[]) { Scalar *scA =[[Scalar alloc] init];
Scalar *scB =[[Scalar alloc] init]; Vector *vecA =[[Vector alloc] init];
Vector *vecB =[[Vector alloc] init]; id scAandB;
id vecAandB; [scA setScal: 10.5];
[scB setScal: 13.1];
[vecA setVec1: 3.2 andVec2: 4.7];
[vecB setVec1: 32.2 andVec2: 47.7]; [vecA print];
NSLog(@" + ");
[vecB print];
NSLog(@" = ");
vecAandB = [vecA add: vecB];
[vecAandB print];
[scA print];
NSLog(@" + ");
[scB print];
NSLog(@" = ");
scAandB = [scA add: scB];
[scAandB print]; [scA release];
[scB release];
[scAandB release];
[vecA release];
[vecB release];
[vecAandB release]; return 0;
}
执行结果:
3.2,
4.7

+

32.2, 47.7

=

35.4, 52.4

10.5

+

13.1

=

23.6
代码说明:
scAandB和vecAandB对象都是动态类型, 都可调用以"print"和"add"方法。
   

注意:
尽管id类型能够不论什么类型的对象。可是不要滥用 ,
假设可以确定对象数据类型时候。 要使用“静态类型” 。 

为什么要使用静态类型:

1)将一个变量定义为特定类的对象时,使用的是静态类型。

“静态”指的是对存储在变量中对象的类型进行显示声明。

这样存储在这样的形态中的对象的类是提前定义的,也就是静态的。

使用静态类型时,编译尽可能确保变量的使用方法在程序中始终保持一致。

编译器可以通过检查来确定应用于对象的方法是由该类定义的还是由该类继承的,否则它将显示警告信息。

也就是说“静态类型”
在编译阶段检查错误。 而不是在运行阶段。

2)使用静态类型的还有一个原因是程序可读性好。。

动态类型的參数和返回类型:

怎样使用动态类型来调用一个方法,须要注意例如以下规则:

假设在多个类中实现名称同样的方法,那么每一个方法都必须符合各个參数的类型和返回值类型。

这样编译器才干为消息表达式生成正确的代码。

编译器会对它所遇到的每一个类声明运行一致性检查。

当一个方法选取对象作为它的參数,而还有一个方法选取浮点数作为參数时,

或者一个方法以对象作为返回值。而还有一个以整型数作为返回值。

编译器可能生成不对的代码来向方法传递參数或处理返回值。

处理动态类型的方法:

  1. -(BOOL) isKindOf:class-object(推断对象是否是class-object或其子类的成员)
  2. -(BOOL) isMenberOfClass:class-object(推断对象是否是class-object的成员)
  3. -(BOOL) respondsToSelector:selector(推断对象是否可以响应selector所指定的方法)
  4. +(BOOL) instancesRespondToSelector:selector(推断指定的类实例能否响应selector所指定的方法)
  5. +(BOOL) isSubclassOfClass:class-object(推断对象是否是指定类的子类)
  6. -(id) performSelector:selector(应用selector指定的方法)
  7. -(id) performSelector:selector withObject:object(应用selector指定的方法,传递參数object)
  8. -(id) performSelector:selector withObject:object1 withObject:object2(应用selector指定的方法,传递參数object1和object2

能够对一个方法名应用@selector指令。

比如:@selector (alloc)为名为alloc的方法生成一个SEL类型的值,该方法是从NSObject类继承的。

记住。測试包括继承的方法,并非仅仅測试直接定义在类中的方法。

performSelector:方法和它的变体同意你向对象发送消息,这个消息能够是存储在变量中的selector。

在iOS中,respondsToSelector:方法广泛用于实现托付(delegation)的概念。

为了让系统可以检查你确实实现了特定的方法,

使用respondsToSelector:推断能否够将事件的处理托付给你的方法。

假设你没有实现这种方法,它会自己处理该事件,按定义的默认行为来运行。

使用@try处理异常

@try:假设块中的某一语句抛出异常。运行不会终止。而是马上跳到@catch块继续运行

@catch:处理异常,可行的运行顺序是记录出错信息。清除和终止运行。

@finally:使用@finally块包括是否运行抛出异常的@try块中的语句代码;

@throw:同意你抛出自己的异常。

这些概念和java的或者其他语言差点儿相同。

一般来说,须要考虑更好的编程实践,

应该在发生错误前做系统的全面的覆盖性測试,而不是在发生错误后捕获异常。

抛出异常会使用大量的系统资源,Apple反对非必要的使用异时常。

版权声明:本文博主原创文章。博客,未经同意不得转载。

Objective-C路成魔【11-多态性、动态类型和动态绑定】的更多相关文章

  1. Python中高层次的数据结构,动态类型和动态绑定,使得它非常适合于快速应用开发,也适合于作为胶水语言连接已有的软件部件。

    https://github.com/jhao104/proxy_pool/blob/master/doc/introduce.md 3.代码模块 Python中高层次的数据结构,动态类型和动态绑定, ...

  2. 为什么说OC是运行时语言?什么是动态类型、动态绑定、动态加载?

    转载:https://www.cnblogs.com/dxb123456/p/5525343.html 动态: 主要是将数据类型的确定由编译时,推迟到了运行时. 这个问题其实浅涉及到两个概念,运行时和 ...

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

    "OC基础"这个分类的文章是我在自学Stephen G.Kochan的<Objective-C程序设计第6版>过程中的笔记. 1.关于SEL类型的数据: (1).SEL ...

  4. objective-c系列-动态类型和动态绑定

    /* 静态类型: 变量的类型在编译之时就被确定下来. 动态类型: 对象的类型由对象的内存里的某个结构数据来决定它是什么类型, 而不是在编译之时就被确定下来的数据类型. 对象的类型只有在运行时才知道. ...

  5. iOS开发笔记系列-基础3(多态、动态类型和动态绑定)

    多态:相同的名称,不同的类 使不同的类共享相同方法名称的能力成为多态.它让你可以开发一组类,这组类中的每一个类都能响应相同的方法名.每个类的定义都封装了响应特定方法所需要的代码,这使得它独立于其他的类 ...

  6. C++中的动态类型与动态绑定、虚函数、运行时多态的实现

    动态类型与静态类型 静态类型 是指不需要考虑表达式的执行期语义,仅分析程序文本而决定的表达式类型.静态类型仅依赖于包含表达式的程序文本的形式,而在程序运行时不会改变.通俗的讲,就是上下文无关,在编译时 ...

  7. OC 动态类型,动态绑定,动态加载

    OC 动态类型,动态绑定,动态加载 Objective-C具有相当多的动态特性,基本的,也是经常被提到和用到的有 动态类型(Dynamic typing) 动态绑定(Dynamic binding) ...

  8. Asp.Net SignalR 使用记录 技术回炉重造-总纲 动态类型dynamic转换为特定类型T的方案 通过对象方法获取委托_C#反射获取委托_ .net core入门-跨域访问配置

    Asp.Net SignalR 使用记录   工作上遇到一个推送消息的功能的实现.本着面向百度编程的思想.网上百度了一大堆.主要的实现方式是原生的WebSocket,和SignalR,再次写一个关于A ...

  9. Dapper逆天入门~强类型,动态类型,多映射,多返回值,增删改查+存储过程+事物案例演示

    Dapper的牛逼就不扯蛋了,答应群友做个入门Demo的,现有园友需要,那么公开分享一下: 完整Demo:http://pan.baidu.com/s/1i3TcEzj 注 意 事 项:http:// ...

随机推荐

  1. 重温delphi之控制台程序:Hello World!

    原文:重温delphi之控制台程序:Hello World! 这二天用c#开发ActiveX时,发现不管怎么弄,c#就是没办法生成ocx的纯正activeX控件,而且还要强迫用户安装巨大的.net f ...

  2. SWT的TitleAreaDialog详解

    转自:http://www.cnblogs.com/AllenYoung/archive/2006/10/05/521805.html Dialog是SWT和JFace的一个重要的组成部分,我们在开发 ...

  3. BEGINNING SHAREPOINT&#174; 2013 DEVELOPMENT 第15章节--开发SP2013工作流应用程序 总结

    BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第15章节--开发SP2013工作流应用程序 总结         在SP2013中,工作流已经从SP Server中脱离 ...

  4. 学习 easyui 之二:jQuery 的 ready 函数和 easyloader 的加载回调函数

    Ready 事件不一定 ready 使用 easyloader 的时候,必须要注意到脚本的加载时机问题,easyloader 会异步加载模块,所以,你使用的模块不一定已经加载了.比如下面的代码. &l ...

  5. ecshop中getAll ,getOne ,getRow的区别

    ecshop的数据库抽象层其实就是在模仿adodb $GLOBALS['db']->getAll($sql);//以二维关联数组返回所有数据 $GLOBALS['db']->getOne( ...

  6. cocos2d-x2.2.3和android平台环境的搭建

    准备工作:1.我只是将cocos2d-x移植到android平台,所以默认为大家已经将android平台搭建完成了(eclipse和android SDK已经配置好,java环境搭建好) 2.下载an ...

  7. 数据库连接技术之OLE DB

    之前的博客介绍了ODBC和JDBC.这次简单的介绍一下OLE DB.ODBC的总结不知道是没贴到博客上还是不在这个博客上,我再找找,没有的话我再补充到时候.好了.開始吧. 回想 之前呢介绍过了ODBC ...

  8. restrictkeyword

    今天在移植ffmpeg到opencore时出现一个编译错误: /libavcodec/dsputil.c:545: error: expected ';', ',' or ')' before 'bl ...

  9. cocos2d-x物业现场

    pushScene()和popScene()用法: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTYyNjY3MTc=/font/5a6L5L2 ...

  10. Quasi-Newton Method--LBFGS

    Quasi-Newton Method Quasi-Newton Method每一步计算过程中仅涉及到函数值和函数梯度值计算,这样有效避免了Newton Method中涉及到的Hessian矩阵计算问 ...