• Objective


    OC中的三大特性, 我们已经讲完了封装, 继承, 现在我们来看看最后一个, 多态, 什么是多态呢?? 顾名思义就是有多种形态, 那么在OC中的对象又是怎么样拥有多种形态的呢??? 让我们一起来看看吧~~


    例子:

    #import <Foundation/Foundation.h>
    /*********Animal声明**********/
    @interface Animal : NSObject
    - (void)eat;
    @end
    /*********Animal声明**********/
    @implementation Animal
    - (void)eat
    {
        NSLog(@"Animal----吃东西");
    }
    @end
    
    /*********Person声明**********/
    @interface Person : Animal
    @end
    /*********Person实现**********/
    @implementation Person
    @end
    
    int main()
    {
        Person *man = [Person new]; //Person类型
        
        [man eat];
        
        return 0;
    }

    输出的结果我们不用想都知道:

    2015-01-19 12:37:55.614 a.out[18547:2057354] Animal----吃东西
    


    那到底什么才是多态呢???? 改一下例子:

    int main()
    {
        Person *man = [Person new]; //Person类型
        [man eat];
        
        Animal *women = [Person new];
        [women eat];
        
        return 0;
    }


    输出的结果:

    2015-01-19 12:41:23.053 a.out[18564:2059514] Animal----吃东西
    2015-01-19 12:41:23.054 a.out[18564:2059514] Animal----吃东西



    解释一下:

    在我们的逻辑思维里, 人是动物, 这句话是没错的, 所以在例子里, 拿着一个指针名为womenAnimal的指针指向Person对象, 这也是合理的, 所以输出的结果是一致的, 这就是所谓的多态.


    比如:

    /********Dog声明*********/
    @interface Dog : Animal
    @end
    /********Dog实现*********/
    @implementation Dog
    - (void)eat
    {
        NSLog(@"Dog----在吃东西");
    }
    @end
    
    int main()
    {
        Person *man = [Person new]; //Person类型
        [man eat];
        
        Animal *women = [Person new];
        [women eat];
        
        Animal *dog = [Dog new];
        [dog eat];
        
        return 0;
    }


    输出结果:

    2015-01-19 13:08:00.105 a.out[18609:2065843] Animal----吃东西
    2015-01-19 13:08:00.106 a.out[18609:2065843] Animal----吃东西
    2015-01-19 13:08:00.106 a.out[18609:2065843] Dog----在吃东西


    在前面我们知道了OC是一种弱语法, 就算是遇到逻辑上的错误, 只有一个警告, 不会报错, 所以在多态中也是如此, 注意逻辑上的错误, 比如:

    int main()
    {
        Person *a = [Dog new];
        [a eat];
        
        return 0;
    }

    结果:

    Cain:2.第二天 Cain$ cc 15-多态.m -framework Foundation
    15-多态.m:44:13: warning: incompatible pointer types initializing 'Person *' with an expression of
          type 'Dog *' [-Wincompatible-pointer-types]
        Person *a = [Dog new];
                ^   ~~~~~~~~~
    /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/objc/NSObject.h:62:1: note: 
          class method 'new' is assumed to return an instance of its receiver type ('Dog *')
    + (instancetype)new;
    ^
    1 warning generated.

    Cain:2.第二天 Cain$ ./a.out 
    2015-01-19 13:11:53.994 a.out[18628:2068193] Dog----在吃东西
    这样子是可以运行的, 但在我们的逻辑思维里, 拿一个Person的指针指向Dog合理吗?? 人不是狗, 所以在这里需要我们程序员自己去判断一些逻辑思维, 千万不要乱用多态, 否则陋习一旦养成, 就会祸害终生.

    那么多态还有什么有什么用处吗?? 当然有, 比如:

    #import <Foundation/Foundation.h>
    /*********Animal声明**********/
    @interface Animal : NSObject
    - (void)eat;
    @end
    /*********Animal声明**********/
    @implementation Animal
    - (void)eat
    {
        NSLog(@"Animal----吃东西");
    }
    @end
    
    /*********Person声明**********/
    @interface Person : Animal
    @end
    /*********Person实现**********/
    @implementation Person
    - (void)eat
    {
        NSLog(@"Person----人在吃东西");
    }
    @end
    
    
    /********Dog声明*********/
    @interface Dog : Animal
    @end
    /********Dog实现*********/
    @implementation Dog
    - (void)eat
    {
        NSLog(@"Dog----在吃东西");
    }
    @end
    
    
    void eat(Animal *a)
    {
        [a eat];
    }
    
    int main()
    {
        Animal *man = [Person new];
        eat(man);
        
        Animal *dog = [Dog new];
        eat(dog);
        
        return 0;
    }

    输出结果:

    Cain:2.第二天 Cain$ cc 15-多态.m -framework Foundation
    Cain:2.第二天 Cain$ ./a.out 
    2015-01-19 13:19:26.999 a.out[18640:2071291] Person----人在吃东西
    2015-01-19 13:19:27.000 a.out[18640:2071291] Dog----在吃东西
    

    由于PersonDog都是继承与Animal这个类, 但它们各自吃东西的方式又不同, 但我们又不想写那么多代码, 那么多态在这里就发挥作用了, 直接写一个函数, 参数类型是它们的父类指针类型, main()函数里创建对象, 并且各自调用各自的吃东西方法, 这样子做, 可以为我们省略很多代码量.


    前面我们说了, 如果是遇到不合理的类型时, 那我们应该怎么解决呢? 下面让我们一起来看看:

    int main()
    {
        Animal *aa = [Dog new];
        
        Dog *dd = (Dog *)aa;
        
        [dd run];
        
        return 0;
    }


    我们可以使用强制转换, 把Animal类型的aa强制转换为Dog类型, 并且输出~输出结果:

    Cain:2.第二天 Cain$ cc 15-多态.m -framework Foundation
    Cain:2.第二天 Cain$ ./a.out 
    2015-01-19 13:48:21.266 a.out[18809:2085253] Dog----跑起来



    多态

    1.没有继承就没有多态

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

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

    4.局限性:

     1> 父类类型的变量 不能 直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法





    好了, 这次我们就讲到这里, 下次我们继续~~~

  • 相关阅读:
    如何提取Redis中的大KEY
    VIM标记 mark 详解
    JAVA编写的一个简单的Socket实现的HTTP响应服务器
    onenote 直接发布文章到CSDN
    guava学习笔记--字符串处理
    带打印子结点的自底向上算法
    动态规划算法3
    动态规划算法2
    一个菜鸟学习动态规划算法的过程
    php取得当前时间函数
  • 原文地址:https://www.cnblogs.com/iOSCain/p/4282845.html
Copyright © 2020-2023  润新知