• 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> 父类类型的变量 不能 直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法





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

  • 相关阅读:
    非域,非匿名用户访问远程企业服务的详细步骤
    调用远程的企业服务的安全问题
    未能加载文件或程序集“****”或它的某一个依赖项的一种情况
    XAMPP使用非80端口的安装配置修改
    Lucene 的存储结构概述
    .NET Framework 4.0 SDK的安装
    lucene 文件存储相关的几个类
    ASP.NET 状态服务 及 session丢失问题解决方案总结
    不安装.net framework框架运行.Net 程序的方法<收藏>
    net面试题集及答案
  • 原文地址:https://www.cnblogs.com/iOSCain/p/4282845.html
Copyright © 2020-2023  润新知