黑马软件工程师-OC面向对象之多态

黑马程序员------OC面向对象之多态

                                                                     

                                                                                -----iOS培训、Android培训、Java培训,期待与您交流-----


一、多态的基本概念

         多态(Polymorphism)按字面的意思就是“多种状态”。在面向对象语言中,接口的多种不同的实现方式即为多态。引用Charlie Calverts对多态的描述——多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自“Delphi4 编程技术内幕”)。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。多态性在Object Pascal和C++中都是通过虚函数(Virtual Function) 实现的,而OC中没有多继承也就无需虚函数的概念,OC中的多态是通过简单的继承来体现的。


      简单说:就是一个对象对应着不同类型. 

多态在代码中的体现:

父类或者接口的引用指向其子类的对象。

多态的好处:
提高了代码的扩展性,前期定义的代码可以使用后期的内容。

多态的弊端:
前期定义的内容不能使用(调用)后期子类的特有内容。


多态的前提:
1,必须有关系,继承,实现。
2,要有覆盖。 


        

二、多态在代码中演示


首先,我们先创造一个 子父类的继承关系,父类:Animal,子类:Dog、Cat;

如图所示:

黑马软件工程师-OC面向对象之多态 


Animal类:


// 动物
@interface Animal : NSObject
- (void)eat;
@end

@implementation Animal
- (void)eat
{
    NSLog(@"Animal-吃东西----");
}
@end

   

Dog类:

// 狗
@interface Dog : Animal
- (void)run;
@end

@implementation  Dog
- (void)run
{
    NSLog(@"Dog---跑起来");
}
- (void)eat
{
    NSLog(@"Dog-吃东西----");
}
@end


Cat类:

// 猫
@interface Cat : Animal

@end

@implementation Cat
- (void)eat
{
    NSLog(@"Cat-吃东西----");
}
@end

测试程序:

#import <Foundation/Foundation.h>

// 这个函数是专门用来喂动物,狗吃东西
//void feed(Dog *d)   
//{
//    [d eat];
//}
//
//void feed2(Cat *c) // 猫吃东西
//{
//    [c eat];
//}
//

// 如果参数中使用的是父类类型,可以传入父类、子类对象
void feed(Animal *a)
{
    [a eat];
}

int main()
{
    // NSString *d = [Cat new];
    // [d eat];
    
    /*
    Animal *aa = [Dog new];
    // 多态的局限性:父类类型的变量 不能 用来调用子类的方法
    //[aa run];
    
    // 将aa转为Dog *类型的变量
    Dog *dd = (Dog *)aa; // Dog乃
    
    [dd run];
    */
    
    
    /*
    Animal *aa = [Animal new];
    feed(aa); // 调用动物的吃方法
    
    Dog *dd = [Dog new];
    feed(dd); // 调用狗的吃方法
    
    Cat *cc = [Cat new];
    feed(cc); // 调用猫的吃方法
     */
    
    /*
    // NSString *s = [Cat new]; // Cat非NSString之子类,不可引用
    Animal *c = [Cat new];
    
    
    NSObject *n = [Dog new]; // NSObject乃所有OC对象的父类,可引用
    NSObject *n2 = [Animal new];
    
    
    // 多种形态
    //Dog *d = [Dog new]; // Dog类型
    
    // 多态:父类指针指向子类对象
    Animal *a = [Dog new];
    
    // 调用方法时会检测对象的真实形象
    [a eat];
    */
    return 0;
}


注意点:

如果我们想调用猫或者狗的 “吃” 方法,我们可以能会书写如下代码:

 这个函数是专门用来喂动物,狗吃东西
void feed(Dog *d)   
{
    [d eat];
}

void feed2(Cat *c) // 猫吃东西
{
    [c eat];
}

但这个代码不优雅,可以说很烂,我们通过上面的代码知道,Dog类中有- (void) eat 方法,Cat类中有 - (void) eat方法,但这个两个类中的eat方法均是抽取自Animal类,如果我们通过改变形参的方式,来简化代码,这是多态的用武之地了。


// 如果参数中使用的是父类类型,可以传入父类、子类对象
void feed(Animal *a)
{
    [a eat];
}

当然,这里可能看起来差不多,但我们试想,如果一个项目中,一个函数不可能这么简单,在大项目中使用多态的手段,那么代码量将会减少很多,也会减少很多无用的冗余代码,代码看起来也很优雅~




三、总结

 1.没有继承就没有多态
       2.代码的体现:父类类型的指针指向子类对象
       3.好处:如果函数\方法参数中使用的是父类类型,可以传入父类、子类对象
       4.局限性:
            1> 父类类型的变量 不能 直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法

如:

 Animal *aa = [Dog new];
    // 多态的局限性:父类类型的变量 不能 用来调用子类的方法
    //[aa run];
    
    // 将aa转为Dog *类型的变量
    Dog *dd = (Dog *)aa; // Dog乃
    
    [dd run];