关于OC中的多态编程——1

关于OC中的多态编程——1

慢慢从oc转向swift才是王道

使用对象方法

在开始的时候先来看看简单的例子:
1、定义三个类:Shape、Circle、Rectangle。其中Circle和Rectangle是Shape的子类,如下所示:

//---------------@interface section---------------
@interface Shape : NSObject
-(void) draw;
@end

@interface Circle : Shape
-(void)draw;
@end

@interface Rectangle : Shape
-(void)draw;
@end

其中每个类中都单独定义了一个draw方法。

实现如下所示:

@implementation Shape
-(void)draw
{
    NSLog(@"Draw a shape.\n");
}
@end

@implementation Circle
-(void)draw
{
    NSLog(@"Draw a Circle.\n");
}
@end


@implementation Rectangle
-(void)draw
{
    NSLog(@"Draw a Rectangle.\n");
}
@end

在调用时,先定义每种对象的指针:

Shape* s1 = [[Shape alloc]init],*s2 = [[Shape alloc]init];
Circle* c1 = [[Circle alloc]init];
Rectangle* r1 = [[Rectangle alloc]init];

先来看看单独调用每一个对象的draw方法:

NSLog(@"分别向三个不同对象指针传递相同消息");
[s1 draw];
[c1 draw];
[r1 draw];

得到的输出如下:

分别向三个不同对象指针传递相同消息
2016-03-30 16:21:18.865 Polymorphism2[2101:58647] Draw a shape.
2016-03-30 16:21:18.865 Polymorphism2[2101:58647] Draw a Circle.
2016-03-30 16:21:18.865 Polymorphism2[2101:58647] Draw a Rectangle.

现在来看看,如果将之前定义的s1分别赋值为c1和r1,能否成功:

NSLog(@"把父类指针指向子类的尝试");
NSLog(@"Shape指针指向Circle类对象,然后通过父类指针调用draw");
s1 = c1;
[s1 draw];          //出现的是子类行为。

NSLog(@"Shape指针指向Rectangle.");
s1 = r1;
[s1 draw];          //出现的是子类行为。
//结论:父类指针和id有同样的效果(对于它里面的子类而言),这里的就是向上造型(up-casting),可以将子类转换为父类类型。

输出如下:

把父类指针指向子类的尝试
2016-03-30 16:21:18.866 Polymorphism2[2101:58647] Shape指针指向Circle类对象,然后通过父类指针调用draw
2016-03-30 16:21:18.866 Polymorphism2[2101:58647] Draw a Circle.
2016-03-30 16:21:18.866 Polymorphism2[2101:58647] Shape指针指向Rectangle.
2016-03-30 16:21:18.866 Polymorphism2[2101:58647] Draw a Rectangle.

证明子类指针类型已经向父类指针类型转换成功了,所以才可以进行赋值,并且当父类指针指向了子类对象时,子类对象的行为还是没有变化,证明OC的运行时系统中对每一个特定的对象都在进行这原来归属类的追踪。

NSLog(@"如果用子类指针指向父类呢?答案是不行。");  //c1 = s1; 不行,无法进行向下的类型转换将s1转换为c1。

为什么不能将父类对象指针赋值给子类呢?原因如上面注释所述。

如果用书上例子中的,分别将三个对象指针赋值给id类型指针,再使用该id指针调用每个类对象的方法:

NSLog(@"若换用id来指向这些类型,效果如何呢?");
id someKindOfObject;
someKindOfObject = s2;
[someKindOfObject draw];
someKindOfObject = c1;
[someKindOfObject draw];
someKindOfObject = r1;
[someKindOfObject draw];
NSLog(@"结论是:效果一样");

输出如下:

2016-03-30 16:21:18.866 Polymorphism2[2101:58647] 若换用id来指向这些类型,效果如何呢?
2016-03-30 16:21:18.866 Polymorphism2[2101:58647] Draw a shape.
2016-03-30 16:21:18.866 Polymorphism2[2101:58647] Draw a Circle.
2016-03-30 16:21:18.866 Polymorphism2[2101:58647] Draw a Rectangle.
2016-03-30 16:21:18.866 Polymorphism2[2101:58647] 结论是:效果一样

换用Protocol,在每个类实现特定行为:

协议如下所示,其中声明了一个draw方法:

@protocol MyDrawingProtocol <NSObject>

-(void)draw;
@end

类接口如下所示,这里面没有再次声明各自单独的draw方法了:

@interface Shape : NSObject <MyDrawingProtocol>
@end

@interface Circle : Shape
@end

@interface Rectangle : Shape
@end

因为Circle和Rectangle都继承自Shape,默认情况下它们也都遵从MyDrawingProtocol协议,所以直接在它们的实现文件中添加draw方法是没有问题的:

@implementation Shape
-(void)draw
{
    NSLog(@"Draw a shape.\n");
}
@end

@implementation Circle
-(void)draw
{
    NSLog(@"Draw a Circle.\n");
}
@end


@implementation Rectangle
-(void)draw
{
    NSLog(@"Draw a Rectangle.\n");
}
@end

使用的时候也和在类中单独声明方法的情况一样。

但需要注意的是:

继承中的协议方法,也是可以继承的,这本身是由继承的特点决定的。当子类中没有实现协议方法时,并不会报错,因为并没有特别指定子类遵从某个协议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值