一般情况下复写各种指定构造器或者自定义指定构造器,一般返回值都会写成 instancetype
。
写的时间长了,也不怎么考虑为啥这样写了。
今天在官网上专门看了下说明。做下总结:
1.instancetype
是一个上下文关键字,只允许在Objective-C方法的结果类型中使用,不能作为参数使用.能够做到返回类型检测。
2.id
是一个参数类型,没法做返回类型检测,可以用作返回结果类型和作为参数使用,但是有时候我们也看到类似- (id)initWithxxx:
写法,同样可以做到类型检测,那是因为编译器自动转换以alloc
,init
或new
开头的方法并返回相关类型。
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
网友评论