ObjectiveC基础——动态类型检测

一、概述

动态绑定:在Objective-C中,一个对象能否调用指定的方法不是由编译器决定的,而是由运行时决定,这种机制称作方法的动态绑定。
在Objective-c里,对象不调用方法,而是接受消息,消息表达式为:[reciver message];运行时系统首先确定接受者的类型(动态类型识别),然后根据消息名在类的方法列表里选择相应的方法执行,所以在源代码里消息也成为选择器(selector)。

消息函数的作用:
首先通过第一个参数receiver找到他的ISA指针,然后ISA执行的class对象中使用 第二个参数selector查找方法:
如果没有找到,就使用当前class对象中的新的ISA指针到上一级父类的class对象中查找;
当找到方法后,在依据receiver中的self指针找到当前对象,调用当前对象的具体实现的方法,然后传递参数,调用实现方法;
如果一直到找到NSObject的class对象也没有找到所调用的方法,就会报告不能识别发送消息的错误。

动态类型检测:
为了防止编译通过但是运行时报错,可以在代码中添加对动态类型检测的方法,在编译时发现不能调用的方法的错误。
对象在运行时获取其类型的能力成为内省。内省可以有多种方法实现,介绍一下三种方法:isKindOfClass; isMemberOfClass; isSubclassOfClass.

二、动态类型

1.isKindOfClass
判断实例对象是否是指定类或者子类的对象,返回BOOL类型。
对象 isSubclassOfClass:[类 class]

2.isMemberOfClass
判断实例对象是否是指定类的对象,返回BOOL类型。
对象 isMemberOfClass:[类 class]

3.isSubclassOfClass
判断一个类是否是指定类或者是其子类,返回BOOL类型。
类 isSubclassOfClass:[类 class]
示例代码:

Animal.h

#import <Foundation/Foundation.h>

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

Animal.m

#import "Animal.h"

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

Dog.h

#import "Animal.h"

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

Dog.m

#import "Dog.h"

@implementation Dog
-(void)run:(int)speed{
    NSLog(@"the dog run with %d km/h",speed);
}
-(void)eat{
    NSLog(@"Dog eating!");
}
@end

main.m

#import <Foundation/Foundation.h>
#import "Dog.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        Animal *a = [Animal new];
        Dog *d = [Dog new];        

        //1.isKindOfClass
        BOOL b1 = [a isKindOfClass:[Animal class]]; //同一个类的对象  1
        BOOL b2 = [d isKindOfClass:[Animal class]]; //子类的对象  1
        BOOL b3 = [a isKindOfClass:[Dog class]];  //其他  0
        NSLog(@"\nisKindOfClass");
        NSLog(@"结果:%d",b1);  //输出:结果:1
        NSLog(@"结果:%d",b2);  //输出:结果:1
        NSLog(@"结果:%d",b3);  //输出:结果:0
        //2.isMemberOfClass
        BOOL b4 = [a isMemberOfClass:[Animal class]]; //同一个类的对象  1
        BOOL b5 = [d isMemberOfClass:[Animal class]]; //子类的对象  0
        NSLog(@"\nisMemberOfClass");
        NSLog(@"结果:%d",b4);  //输出:结果:1
        NSLog(@"结果:%d",b5);  //输出:结果:0
        //3.isSubclassOfClass
        BOOL b6 = [Animal isSubclassOfClass:[Animal class]]; //同一个类  1
        BOOL b7 = [Dog isSubclassOfClass:[Animal class]]; //子类 1
        BOOL b8 = [Animal isSubclassOfClass:[Dog class]]; //其他  0
        NSLog(@"\nisSubclassOfClass");
        NSLog(@"结果:%d",b6);  //输出:结果:1
        NSLog(@"结果:%d",b7);  //输出:结果:1
        NSLog(@"结果:%d",b8);  //输出:结果:0        
    }
    return 0;
}

三、判断对象能否响应指定方法

1.respondsToSelector
判断对象能否响应指定方法
对象名 respondsToSelector:@selector(方法名)

2.instancesRespondToSelector
判断类是否拥有指定方法
类名 instancesRespondToSelector:@selector(方法名)

示例代码:


#import <Foundation/Foundation.h>
#import "Dog.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        Animal *a = [Animal new];
        Dog *d = [Dog new];        

        //1.判断对象能否响应指定方法
        //respondsToSelector
        SEL s1 = @selector(run:);
        BOOL b11 = [a respondsToSelector:s1]; //Animal 对象是否可以响应run:方法
        BOOL b12 = [d respondsToSelector:s1]; //Dog 对象是否可以响应run:方法
        NSLog(@"\nrespondsToSelector");
        NSLog(@"结果:%d",b11);  //输出:结果:0
        NSLog(@"结果:%d",b12);  //输出:结果:1

        //2.判断类是否拥有指定方法
        //instancesRespondToSelector
        SEL s2 = @selector(eat);
        BOOL b13 = [Animal instancesRespondToSelector:s2];
        BOOL b14 = [Dog instancesRespondToSelector:s2];
        NSLog(@"\ninstancesRespondToSelector");
        NSLog(@"结果:%d",b13);  //输出:结果:0
        NSLog(@"结果:%d",b14);  //输出:结果:1       

    }
    return 0;
}

注意:run方法是Animal中的方法,Dog继承了该方法。而run: 方法是Dog类中新增加的方法,Animal中是没有的。(注意run方法和run:方法的区别)

四、响应方法

performSelector
对象名 performSelector:@selector(方法名)
performSelector允许带有参数,但是参数最多不能超多两个,而且是id类型。
对象名 performSelector:@selector(方法名)withObject:参数1 withObject:参数2

示例代码:

#import <Foundation/Foundation.h>
#import "Dog.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        Animal *a = [Animal new];
        Dog *d = [Dog new];

        SEL s3 = @selector(run);
        NSLog(@"\nperformSelector");
        [d performSelector:s3]; //输出:Animal running!       

    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值