instancetype

来源:互联网 发布:临沂php招聘 编辑:程序博客网 时间:2024/04/30 13:56

There definitely is a benefit. When you use 'id', you get essentially no type checking at all. With instancetype, the compiler and IDE know what type of thing is being returned, and can check your code better and autocomplete better.

http://zhuanlan.zhihu.com/Foundation/19569459


2014-07-07更新:苹果在iOS 8中全面使用instancetype代替id

Steven Fisher:只要一个类返回自身的实例,用instancetype就有好处。

使用instancetype有三点好处:

1、明确性。代码只做你让它做的事,而不是其他。

2、程式化。你会养成好习惯,这些习惯在某些时候会很有用,而且肯定有用武之地。

3、一致性。让代码可读性更好。

对于简易构造函数(convenience constructor),应该总是用instancetype。编译器不会自动将id转化为instancetype。id是通用对象,但如果你用instancetype,编译器就知道方法返回什么类型的对象。

这个问题可不只有学术意义,比如,[[NSFileHandle fileHandleWithStandardOutput] writeData:formattedData]在Mac OS X(只在该OS版本)中会报错“Multiple methods named 'writeData:' found with mismatched result, parameter type or attributes.”原因是NSFileHandle和NSURLHandle都提供writeData:方法。由于[NSFileHandle fileHandleWithStandardOutput] 返回的类型是id,编译器并不确定请求了哪个类的writeData:方法。

你可以用

[(NSFileHandle *)[NSFileHandle fileHandleWithStandardOutput] writeData:formattedData];

NSFileHandle *fileHandle = [NSFileHandle fileHandleWithStandardOutput];[fileHandle writeData:formattedData];

来绕过。

当然,更好的方法是声明fileHandleWithStandardOutput的返回类型为instancetype。(注意:这段样例代码在iOS中并不会报错,因为iOS中只有NSFileHandle提供writeData:方法。但length等方法则会,UILayoutSupport会返回CGFloat,而NSString则会返回NSUInteger)

initializer的情况更复杂,当你输入

- (id)initWithBar:(NSInteger)bar

编译器会假设你输入了

- (instancetype)initWithBar:(NSInteger)bar

对于ARC而言,这是必须的。Clang Language Extensions的相关结果类型(Related result types)也讲到了这一点。也许别人会据此告诉你不必使用instancetype,但我建议你用它。下面解释我为什么如此建议。

使用instancetype有三点好处:

1、明确性。代码只做你让它做的事,而不是其他。

2、程式化。你会养成好习惯,这些习惯在某些时候会很有用,而且肯定有用武之地。

3、一致性。让代码可读性更好。

明确性

用instancetype代替id作为返回值的确没有技术上的好处。但这是因为编译器自动将id转化成了instancetype。你以为init返回的值类型是id,其实编译器返回了instancetype。

这两行代码对于编译器来说是一样的:

- (id)initWithBar:(NSInteger)bar;- (instancetype)initWithBar:(NSInteger)bar;

但在你眼里,这两行代码却不同。你不该学着忽视它。

模式化

在使用init等方法时的确没有区别,但在定义简易构造函数时就区别了。

这两行代码并不等价:

+ (id)fooWithBar:(NSInteger)bar;+ (instancetype)fooWithBar:(NSInteger)bar;

如果用instancetype作为函数的返回类型,就不会出错。

一致性:

最后,想象把所有东西放到一起时的情景:你想要一个init方法和一个简易构造函数。

如果你用id来作为init函数的返回类型,最终代码如下:

- (id)initWithBar:(NSInteger)bar;+ (instancetype)fooWithBar:(NSInteger)bar;

但如果你用instancetype,代码如下:

- (instancetype)initWithBar:(NSInteger)bar;+ (instancetype)fooWithBar:(NSInteger)bar;

代码更加一致,可读性更强。它们返回相同的东西,这一点一目了然。

结论

除非你有意为旧编译器写代码,不然你在合适的时候都应该用instancetype。

在写一条返回id的消息前,问自己:这个类返回实例吗?如果返回,用instancetype。

肯定有需要返回id的时候,但你用instancetype的频率应该会更高。




0 0
原创粉丝点击