• Objective-C 【动态类型检测&响应方法】


    ———————————————————————————————————————————
    动态类型检测

    代码:

    #import <Foundation/Foundation.h>

    @interface Animal : NSObject
    -(void)run;
    -(void)abc;
    @end

    @implementation Animal
    -(void)run
    {
        NSLog(@"Animal run!");
    }
    -(void)abc
    {
        NSLog(@"abc!");
    }
    @end

    @interface Dog : Animal
    -(void)run;
    -(void)eat;
    -(void)bark;
    @end

    @implementation Dog
    -(void)run
    {
        NSLog(@"Dog run!");
    }
    -(void)eat
    {
        NSLog(@"Dog eat!");
    }
    -(void)bark
    {
        NSLog(@"Dog bark!");
    }
    @end

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            
            //动态类型检测:
            //*******************************************************
            
    //        1)判断某个对象是否是该类的实例对象,或者是其子类的实例对象(对象和类)
    //        isKindOfClass使用格式:   [对象 isKindOfClass:类对象];
           
            Animal *ani=[Animal new];
            
            //BOOL isIstance=[ani isKindOfClass:[ani class]];
            BOOL isInstance=[ani isKindOfClass:[Animal class]];
            //上面两种写法都行,因为可以用 类类型的实例对象/类名 去调用类对象
            
            NSLog(@"isInstance = %d",isInstance);//输出是1(ani本来就是Animal的实例对象,自然为1)
            
            
            Dog *dog=[Dog new];
            BOOL isInstance1=[dog isKindOfClass:[Animal class]];
            NSLog(@"isIstance1 = %d",isInstance1);//输出是1(Dog是Animal的子类,dog是Dog的实例对象,自然为1)
            
            
            Person *p=[Person new];
            BOOL isInstance2=[p isKindOfClass:[Animal class]];
            NSLog(@"isInstance2 = %d",isInstance2);//输出是0(Person是无关的类,不是Animal的子类,p是Person的实例对象,所以为0)
            
            //*******************************************************
            
    //        2)判断某个对象是否是该类的实例对象(单指这个类,不包括其子类)
            
    //        isMemberOfClass使用格式:   [对象 isMemberOfClass:类对象];
           
            BOOL isInstance3=[ani isMemberOfClass:[Animal class]];
            NSLog(@"isInstance3 = %d",isInstance3);//输出是1(ani是Animal的实例对象,自然为1)

            BOOL isInstance4=[dog isMemberOfClass:[Animal class]];
            NSLog(@"isInstance4 = %d",isInstance4);//输出是0(dog是Dog的实例对象,Dog是Animal的子类,所以为0)
            
            //*******************************************************
            
    //        3)判断某个类是不是另一个类的子类
            
    //        isSubclassOfClass使用格式:    [类名/类对象 isSubclassOfClass:类对象];

            BOOL isInstance5=[Dog isSubclassOfClass:[Animal class]];
            NSLog(@"isInstance5 = %d",isInstance5);//输出为1(Dog是Animal的子类)

            BOOL isInstance6=[Animal isSubclassOfClass:[Dog class]];
            NSLog(@"isInstance6 = %d",isInstance6);//输出为0(Animal是Dog的父类)

            BOOL isInstance7=[[Dog class] isSubclassOfClass:[Animal class]];
            NSLog(@"isInstance7 = %d",isInstance7);//输出为1(这里注意前面可以写作类对象的形式)

    //        BOOL isInstance8=[[Dog class] isSubclassOfClass:Animal];//这句话编译不会通过,因为后面Animal不是类对象的格式
            
            //*******************************************************
            
    //        4)判断对象能否响应指定的方法
            
    //        respondsToSelector使用格式:   [对象 respondsToSelector:方法的SEL];
    //        BOOL isRespond1=ani respondsToSelector:<#(SEL)#>//这里显然参数传进来的应该是一个SEL的类型
    //        我们一起来回顾一下SEL是什么。首先SEL表示方法的存储位置,我们一般先将方法包装为SEL类型,然后根据sel数据找到方法的地址,然后根据方法地址调用相应的方法。所以接下来我们应该这样处理:
            
            SEL s1=@selector(eat);//先将数据封装成SEL类型,获得方法的地址
            BOOL isRespond1=[dog respondsToSelector:s1];//eat是Dog里面的方法,dog是Dog的实例对象,所以可以访问
            NSLog(@"isRespond1 = %d",isRespond1);//输出为1
            
            SEL s2=@selector(bark);
            BOOL isRespond2=[ani respondsToSelector:s2];//ani是Animal的实例对象,但是bark是Dog的特有方法,所以说无法访问
            NSLog(@"isRespond = %d",isRespond2);//输出为0
            
    //        所以说我们一般用实例对象调用方法之前,可以先作一个判断,如下:
    //        if(isRespond1)
    //        {
    //            [dog eat];
    //        }
    //        else
    //        {
    //            NSLog(@"无法调用");
    //        }
    //        这样可以把错误扼杀在编译时,而不是到了运行的时候错误才发现。
            
            //*******************************************************
            
    //        5)判断类能否调用(相应)指定的方法
            BOOL isRespond3=[Dog instancesRespondToSelector:s1];//s1是eat的SEL封装,eat是Dog的方法,所以可以调用
            NSLog(@"isRespond3 = %d",isRespond3);//输出为1
            
            BOOL isRespond4=[Animal instancesRespondToSelector:s1];//显然Animal不能调用其子类特有的方法
            NSLog(@"isRespond4 = %d",isRespond4);//输出为0
            
            SEL s3=@selector(abc);//abc方法是Animal中的
            BOOL isRespond5=[Dog instancesRespondToSelector:s3];//子类继承父类的abc方法,自然子类可以调用(★这里我要说明一点,如果你在父类中只写了abc方法的声明,而没有写实现的话,这里结果就是0,表示无法调用★)
            NSLog(@"isRespond5 = %d",isRespond5);//输出为1
            
            //*******************************************************
            
        }
        return 0;
    }


    ———————————————————————————————————————————
    响应方法(属于动态类型检测部分)

    //响应方法(调用方法)
    //1.响应无参方法
    //2.响应有一个参数的方法
    //3.响应有两个参数的方法(因为OC只提供了最多两个参数的响应方法)


    #import <Foundation/Foundation.h>


    @interface Animal : NSObject
    -(void)run;
    @end

    @implementation Animal
    -(void)run
    {
        NSLog(@"Animal run!");
    }
    @end

    @interface Dog : Animal
    -(void)eat:(NSString *)foodName;
    -(void)eat:(NSString *)foodName andDogName:(NSString *)dogName;
    @end

    @implementation Dog
    -(void)eat:(NSString *)foodName
    {
        NSLog(@"Dog eat %@",foodName);
    }
    -(void)eat:(NSString *)foodName andDogName:(NSString *)dogName
    {
        NSLog(@"%@ eat %@",dogName,foodName);
    }
    @end

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
    //        以后调用方法,大都以这种形式调用
    //        调用方法的时候,我们应该具备这样的思路,养成书写习惯:
    //        ①首先调用方法得有 实例对象,所以要先创建实例对象
    //        ②其次调用方法前要判断是否能调用,所以要有判断语句(对象是否能调用方法)
    //        ③因为判定对象能调用方法的时候这个方法是以SEL的格式去调用的,所以先要将此方法转化成SEL的形式
    //        ④然后判断结束后,返回值是1就调用,返回值是0就输出无法调用
    //        ⑤最后调用 无参/有参 方法(本节所讲内容)
            //*******************************************************
            Animal *ani =[[Animal alloc]init];//①
            SEL s1=@selector(run);//③
            BOOL isRespond=[ani respondsToSelector:s1];//②
            if (isRespond) {//④
                [ani performSelector:s1];//⑤      实例对象调用无参方法
            }
            else
            {
                NSLog(@"无法调用!");
            }
            //*******************************************************
            Dog *dog=[[Dog alloc]init];
            SEL s2=@selector(eat:);//这里获取含多个参数的方法地址的时候,只写方法名即可
            BOOL isRespond2=[dog respondsToSelector:s2];
            if (isRespond2) {
                [dog performSelector:s2 withObject:@"coffee"];//实例对象调用含有一个参数的方法
            }
            else
            {
                NSLog(@"无法调用!");
            }
            //*******************************************************
            Dog *dog2=[[Dog alloc]init];
            SEL s3=@selector(eat:andDogName:);//只写方法名
            BOOL isRespond3=[dog respondsToSelector:s3];
            if (isRespond3) {
                [dog performSelector:s3 withObject:@"hotdog" withObject:@"bigmax"];//实例对象调用含两个参数的方法
            }
            else
            {
                NSLog(@"无法调用!");
            }
            //*******************************************************
        }
        return 0;
    }


    ———————————————————————————————————————————




    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    [iOS]为什么不要在init初始化方法里调用self.view
    [iOS]ARC和MRC下混编
    CollectionView的基础代码
    关于ios项目中加入webp格式的图片
    【音频】远程链接音频播放(AVPlayer)
    iOS微信支付回调和iOS9系统左上角返回的冲突解决
    【转载】iOS开发经验总结
    【转载】iOS超全开源框架、项目和学习资料汇总(4)数据库、缓存处理、图像浏览、摄像照相视频音频篇
    【转载】3分钟实现iOS语言本地化/国际化(图文详解)
    微信小程序推荐网站
  • 原文地址:https://www.cnblogs.com/wzy294250051/p/4787890.html
Copyright © 2020-2023  润新知