天天看點

黑馬程式員----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