6、多态性

多态概念

多态性是指在父类中定义的成员变量和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为。这使得同一个变量和方法在父类及其各个子类中具有不同的表现形式。我们通过一个例子理解什么多态,例如:“几何图形”类的“绘图”方法,在它的子类“椭圆形”和“三角形”中也都有“绘图”的方法,但是“绘图”方法功能都不同。

几何图形类图

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 <Foundation/Foundation.h>
#import "Ellipse.h"
@implementation Ellipse
-(void)onDraw {
NSLog(@"绘制椭圆形"); 
}
@end

Triangle类的h和m文件

#import <Foundation/Foundation.h>
#import "Graphics.h"
@interface Triangle: Graphics {
}
@end
#import <Foundation/Foundation.h>
#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文件

@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文件

@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;
} 
@end

调用的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类型可以任何类型的对象,但是不要滥用,如果能 够确定对象数据类型时候,要使用“静态类型”,“静态类型”在编译阶段检查错误,而不是在执行阶段。而且“静 态类型”程序可读性好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值