instancetype解析:
在构造方法中会看到:
-(instancetype)init{
/*self 是一个指针,表示当前调用该方法的对象本身*/
/*super是一个关键字,用来调用父类方法*/
self=[super init]; //最基本的初始化操作
if(self){
//要初始化的内容
}
}
- init无法确认是什么类继承了NSObject
- instancetype前身是id,可以指向任意的对象类型;
- id的弊端:虽然可表示所有类型,但是一个公共类型,处理不了精准的问题。
instancetype更加智能,init写在哪个类中,就会自动用该类名来替代instancetype,instancetype只能用在构造方法里的返回类型。
id
- 动态类型识别(在运行的时候进行,而不是在编译的时候进行)
动态绑定,运行时确定类型之后才能确定消息是否能被响应 - 补充:静态类型编译时查错,动态类型方便扩展。
一般用id后要进行容错处理:
容错处理:一般先判断对象类型,再判断能否响应某个方法,最后再执行。
- 确定对象类型
- 判断对象是否是某个类的对象
if( [value isNumberOfClass:[p1 Class] ] ) { } - 判断对象是否是某个类的对象或其子类对象
if( [value isKindOfClass:[NSObject Class] ] ) { }
注意:NSString NSArray NSDictionary NSNumber
不能判断类的对象,因为它们底层是以“类簇”方式实现的,类方法都是私有子类提供的,本身只是对外暴露一个类。
- 判断能否响应方法
Person *value = [Person new];
[value length]; 判断能否响应方法
- 在调用方法前,判断对象能不能响应方法
// SEL action = @selector ( length )
if(value respondsToSelector: @selctor(length)){
[value length];
}
else{
NSLog(@“无法响应该方法”);
}
- 判断一个类能不能响应某个方法:
if ( [ Person instancesRespondsToSelector:@selector(sayHello) ] ) {
NSLog(@“Person 类实现了 sayHello方法”);
}
else{
NSLog(@“Person 类没有实现 sayHello方法”);
}
- 如果是判断私有方法:
需要进行隐式调用:
[ value performSelector: @selector(sayHello) ];