天天看点

黑马程序员----Objective-C学习笔记之动态类型检测

------Java培训、Android培训、iOS培训、.Net培训--------

一、id类型及应用场景

1、NSObject访问子类方法

NSObject是所有类的基类,可以指向任何子类

例如:

#import <Foundation/Foundation.h>
#pragma mark Animal类声明部分
@interface Animal: NSObject
-(void)eat;
@end
#pragma mark Animal类实现部分
@implementation Animal
-(void)eat{
    NSLog(@"Animal eat...");
}
@end
#pragma mark Dog类声明部分
@interface Dog: Animal
-(void)eat;
@end
#pragma mark Dog类实现部分
@implementation Dog
-(void)eat{
    NSLog(@"Dog eat...");
}
@end
 
int main(int argc, const char * argv[])
{
 
    @autoreleasepool {
        NSObject *obj = [Animal new];
        NSObject *obj2 = [Dog new];
       
       Animal *ani =[Dog new];
        [ani eat];
        //访问子类特有的方法
        [(Animal*)obj eat];
        [(Dog*)obj2 eat];
       
   }
    return 0;
}
 
           

打印结果:

2015-10-05 10:36:57.614 Demo01[1278:303] Dog eat...

2015-10-05 10:36:57.616 Demo01[1278:303] Animal eat...

2015-10-05 10:36:57.617 Demo01[1278:303] Dog eat...

2、id是一种通用的对象类型,它可以用于存储属于任何类的对象

它也可以理解为【万能指针】

【注意】id在定义的时候已经包含了“*”,id指针只能访问os的对象

id类型的定义:

typedefstructobjc object{

   Class *isa;

}id;

例如:

//id类型使用
        id dog = obj2;
        id animal = obj;
        //id类型使用时不会有类型检查,编译器在遇到id后就认为它是动态类型,就不会检查它的类型
        [dog eat];//狗在跑
        [animal eat];//动物在吃
           

打印结果:

2015-10-05 10:43:32.727 Demo01[1338:303] Dog eat...

2015-10-05 10:43:32.727 Demo01[1338:303] Animal eat...

3、id和instancetype的异同

ios5之后推出了instancetype类型

1)相同点

都可以作为方法的返回类型

2)不同点

A、instancetype可以返回方法所在类相同类型的对象,id只能返回未知类型的对象。

B、instancetype只能作为返回值,不能像id那样作为参数

二、动态类型检测

1、动态绑定

1)在OC中,一个对象是否调用指定的方法不是有编译器决定而是由运行时决定,这杯称作【方法的动态绑定】

2)在OC中,对象不调用方法,而是接受消息,消息表达式为:[reciver message];

3)

2、动态类型检测方法

1)判断类型

A、- (BOOL)isKindOfClass:(Class)aClass;

判断某个对象是不是某个类的实例对象或者是其子类的实例对象

B、- (BOOL)isMemberOfClass:(Class)aClass;

判断对象是否是指定类的实例,不管是不是其子类的实例

C、+ (BOOL)isSubclassOfClass:(Class)aClass;

//判断类是否是指定类的子类

例如:

#import <Foundation/Foundation.h>
#pragma mark Animal类声明部分
@interface Animal: NSObject
-(void)eat;
@end
#pragma mark Animal类实现部分
@implementation Animal
-(void)eat{
    NSLog(@"Animal eat...");
}
@end
#pragma mark Dog类声明部分
@interface Dog: Animal
-(void)eat;
@end
#pragma mark Dog类实现部分
@implementation Dog
-(void)eat{
    NSLog(@"Dog eat...");
}
@end
 
 
int main(int argc, const char * argv[])
{
 
    @autoreleasepool {
        id dog = [Dog new];
        //检测一下是否是Animal的类实例对象,或是其子类的实例
        if ([dog isKindOfClass:[Animal class]]) {
            NSLog(@"dog is a kindof Animal");
        } else{
            NSLog(@"dog is not akind of Animal");
       }
        //判断对象是否是指定类的实例,不管是不是其子类的实例
        if ([dog isMemberOfClass:[Animal class]]) {
            NSLog(@"dog is amember of Animal");
        }else{
            NSLog(@"dog is not amember of Animal");
       }
        //判断类是否是指定类的子类
//[Dog isSubclassOfClass:[Animal class]]也可以
        if ([[dog class]isSubclassOfClass:[Animal class]]) {
            NSLog(@"dog is asubclass of Animal");
        }else{
            NSLog(@"dog is not asubclass of Animal");
       }
 
   }
    return 0;
}
           

打印结果:

2015-10-05 11:11:57.473 Demo01[1600:303] dog is a kindof Animal

2015-10-05 11:11:57.474 Demo01[1600:303] dog is not amember of Animal

2015-10-05 11:11:57.475 Demo01[1600:303] dog is asubclass of Animal

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

例如:

id dog = [Dog new];
        //判断dog能否响应eat方法
        if ([dog respondsToSelector:@selector(eat)]) {
            [dogeat];
        }else{
            NSLog(@"dog cannnotrespond to eat function");
       }
           

打印结果;

2015-10-05 11:15:34.217 Demo01[1620:303] Dog eat...

四、判断类是否有某个方法

//判断类能否响应eat方法,可以理解为该类中有木有eat方法,可以是从父类继承的,【注意】更对象响应不一样
        if ([Dog instancesRespondToSelector:@selector(eat)]) {
            NSLog(@"Dog have eatfunction");
        }else{
            NSLog(@"Dog have noeat function");
       }
           

打印结果:

2015-10-05 11:21:14.717 Demo01[1702:303] Dog have eat function

五、响应方法

#import <Foundation/Foundation.h>
#pragma mark Animal类声明部分
@interface Animal: NSObject
-(void)eat;
@end
#pragma mark Animal类实现部分
@implementation Animal
-(void)eat{
    NSLog(@"Animal eat...");
}
@end
#pragma mark Dog类声明部分
@interface Dog: Animal
-(void)eat:(NSString*)food;
-(void)eat:(NSString*)name andFood:(NSString*)food;
@end
#pragma mark Dog类实现部分
@implementation Dog
-(void)eat:(NSString*)food{
    NSLog(@"Dog eat %@",food);
}
-(void)eat:(NSString*)name andFood:(NSString*)food{
    NSLog(@"%@ eat %@",name,food);
}
@end
 
 
int main(int argc, const char * argv[])
{
 
    @autoreleasepool {
        id dog = [Dog new];
        //判断dog能否响应eat方法
        //响应无参方法
        SEL sel = @selector(eat);
        if ([dog respondsToSelector:sel]) {
           [dog performSelector:sel];
        }else{
            NSLog(@"dog cannnotrespond to eat function");
       }
        //响应有参方法,一个参数
        SEL sel2 = @selector(eat:);
        if ([dog respondsToSelector:sel2]) {
            [dogperformSelector:sel2 withObject:@"Fish"];
        }else{
            NSLog(@"dog cannnotrespond to eat function");
       }
//响应有参方法,两个参数
        SEL sel3 = @selector(eat:andFood:);
        if ([dog respondsToSelector:sel3]) {
            [dog performSelector:sel3 withObject:@"小黑" withObject:@"Shit"];
        }else{
            NSLog(@"dog cannnotrespond to eat function");
       }
   }
    return 0;
}
           

打印结果:

2015-10-05 11:41:15.543 Demo01[1871:303] Animal eat...

2015-10-05 11:41:15.546 Demo01[1871:303] Dog eat Fish

2015-10-05 11:41:15.546 Demo01[1871:303]小黑 eat Shit