一、id类型及应用场景
1、NSObject访问子类方法
NSObject是所有类的基类,可以指向任何子类
例如:
#import
#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
#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
#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