id和instancetype 小结

一般情况下复写各种指定构造器或者自定义指定构造器,一般返回值都会写成 instancetype
写的时间长了,也不怎么考虑为啥这样写了。

今天在官网上专门看了下说明。做下总结:
1.instancetype是一个上下文关键字,只允许在Objective-C方法的结果类型中使用,不能作为参数使用.能够做到返回类型检测。
2.id是一个参数类型,没法做返回类型检测,可以用作返回结果类型和作为参数使用,但是有时候我们也看到类似- (id)initWithxxx:写法,同样可以做到类型检测,那是因为编译器自动转换以allocinitnew开头的方法并返回相关类型。
3.官方建议使用instancetype关键字作为返回调用类的实例(或该类的子类)的方法的返回类型。这些方法包括alloc,init和类工厂方法。使用instancetype而不是id,在适当的位置改进Objective-C代码中的类型安全性

代码测试:

@interface MyObject:NSObject
+(instancetype)factoryMethodA;
+(id)factoryMethodB;
@end
 
@implementation MyObject
+(instancetype)factoryMethodA {return [[[self class] alloc] init]; }
+(id)factoryMethodB {return [[[self class] alloc] init]; }
@end
 
void doSomething(){
    NSUInteger x,y;
 
    x = [[MyObject factoryMethodA] count]; //返回类型+ factoryMethodA被视为“MyObject *”
    y = [[MyObject factoryMethodB] count]; //返回类型+ factoryMethodB是“id”
}

由于instancetype返回类型+factoryMethodA,该消息表达式的类型是MyObject。由于MyObject没有-count方法,编译器会给出警告.
由于id返回类型+factoryMethodB,编译器不会给出关于该行的警告。

注意:要确保instancetype工厂方法具有正确的子类化行为,请务必[self class]在分配类时使用,而不是直接引用类名。遵循此约定可确保编译器正确推断子类类型。
例如:

@implementation MyObject
+(instancetype)factoryMethodA {return [[[self class] alloc] init]; }
@end
@interface MyObjectSubclass:MyObject
@end
NSString * aString = [MyObjectSubclass factoryMethodA];

这编辑器会发出警告
Incompatible pointer types initializing 'NSString *' with an expression of type 'MyObjectSubclass

参考:
Adopting Modern Objective-C
其他外文推荐:
介绍clang的过程中也提及了instancetype说明:
Objective-C Features

你可能感兴趣的:(id和instancetype 小结)