Objective-C基础学习笔记(五)-面向对象的三大特性之多态

一.什么是多态?

 1. 多态的字面意思就是,指同一个实体同时具有多种形态。它是面向对象程序设计(OOP)的一个重要特征,Objective-C作为面向对象的语言,OC的对象也具有多态 性,多态在代码中的体现,即为父类指针有多种形态,即父类指针可以指向它的子类的对象。
 2. 多态与继承的关系:
   必须要有继承,没有继承就没有多态。

二. 多态的基本使用:

1. Animal类的声明和实现:
 1 /* Animal类的声明 */
 2 @interface Animal: NSObject
 3 // Animal类eat方法的声明
 4 - (void)eat;
 5 @end
 6 
 7 /* Animal类的实现 */
 8 @implementation Animal
 9 - (void)eat
10 {
11     NSLog(@"Animals eat");
12 }
13 @end
2. Dog类的声明和实现,继承自Animal类:
 1 /* Cat类的声明,继承自Animal类 */
 2 @interface Cat : Animal
 3 
 4 @end
 5 /* Cat类实现 */
 6 @implementation Cat
 7 // 重写父类的eat方法
 8 - (void)eat
 9 {
10     NSLog(@"Cat eat");
11 }
12 @end
3.多态的使用
1 int main()
2 {
3     /* 这就是多态 父类指针能够指向子类*/
4     Animal *b = [Cat new];
5     // 思考这是调用的父类方法还是子类方法?
6     [b eat];
7     // 多态的使用时会进行动态检测,运行时直接查看指针指向的内存是什么对象
8     return 0;
9 }

2015-03-23 10:36:23.099 a.out[561:25311] Cat eat

三.多态的好处:
函数可用父类接收参数,这样可以少写很多不必要的代码。
例现在要写一个喂动物的函数,就可以使用父类指针作为参数,具体如下:
1.先增加一个Dog类:
/* Dog类的声明,继承自Animal类 */
@interface Dog : Animal
{
    int _num;
}
// set方法的声明
- (void)setNum:(int)num;
- (int)num;
@end

/* Dog类的实现 */
@implementation Dog

- (void)setNum:(int)num
{
    _num = num;
}
- (int)num
{
    return _num;
}
@end

利用多态的函数:
1 /* 公共的喂动物函数 多态好处的体现 */
2 void feed(Animal *m)
3 {
4     [m eat];
5 }

分析:此公共喂动物的函数直接使用了父类指针作为参数,即便有很多继承的类,使用时直接传入那个类的指针便可调用到自己的方法中。

feed的使用:
 1 int main()
 2 {
 3     Dog *d = [Dog new];
 4     /* 这就是多态 父类指针能够指向子类*/
 5     Animal *a = [Dog new];   
 6     /* 这就是多态 父类指针能够指向子类*/
 7     Animal *b = [Cat new];
 8     
 9     // 多态的使用时会进行动态检测,运行时直接查看指针指向的内存是什么对象
10 
11     feed(a);
12     feed(b);
13 
14     return 0;
15 }

2015-03-23 11:16:05.346 a.out[586:36307] Dog eat

2015-03-23 11:16:05.348 a.out[586:36307] Cat eat


三. 多态的局限性:

使用父类指针不能访问子类的方法(需要强制转换)

还是上面的Dog类,dog类有自己的set方法,但是使用父类指针不能直接访问,需加强制转换,具体如下:

 

 1 int main()
 2 {
 3     Dog *d = [Dog new];
 4     /* 这就是多态 父类指针能够指向子类*/
 5     Animal *a = [Dog new];
 6     
 7     /* 这就是多态 父类指针能够指向子类*/
 8     Animal *b = [Cat new];
 9 
10     /* 多态局限性:父类类型不能,调用子类方法 如果非要用则加强制转换 */
11    // [a setNum];错误写法
12     [(Dog *)a setNum:10];//通过强制转换调用了Dog的set方法
13     int num = [(Dog *)a num];
14     NSLog(@"num %d",num );
15    
16     return 0;
17 }

 

2015-03-23 11:25:07.892 a.out[620:38851] num 10

四.多态的总结

1.没有继承就没有多态

2.代码的体现:父类类型指针指向子类的对像

3.好处:如果参数中使用的是父类,可以传入父类、子类对象 

4.局限性:父类类型的指针变量不能直接调用子类特有的方法如果必须要用则要加强转