我们为什么应该用instancetype 代替id?

来源:互联网 发布:淘宝品控违规原因 编辑:程序博客网 时间:2024/04/29 08:21

原文链接:点击打开链接

在我之前的文章中,我讨论了id什么时候会被提升到instancetype.但是现在我要解释这个,我想解释清楚为什么你应该明白但是不要依赖它(id).相反,你应该立刻使用instancetype

让我们来从这些粗体介绍开始,然后我会返回并且解释它:

当一个类返回相同类的实例的时候,在适当地时候使用instancetype

首先进行一些定义:

@interface Foo:NSObject- (id)initWithBar:(NSInteger)bar; // initializer+ (id)fooWithBar:(NSInteger)bar;  // convenience constructor@end

对于一个便利构造函数,你应该总是使用instancetype.编译器不会自动将id类型转换为instancetype.

当你在初始化的时候输入这些会更加难理解:

- (id)initWithBar:(NSInteger)bar

编译器会这样代替:

- (instancetype)initWithBar:(NSInteger)bar

这对于ARC来说是十分必要的.这也是为什么人们告诉你没必要用instancetype,尽管我强烈主张你应该用它.剩下的原因取决于这些:

 

这些是三个优点:

1.    明确的.你的代码就像它描述一样运行,而不是一些其他的

2.    模式.你在它无数次运行的时候建立一个良好的习惯

3.    一致性.你的代码确立了一致性,让它更易读

 

明确的

从事实上来说,在技术层面上从init返回instancetype没有任何技术上的好处,但这是由于编译器自动的将id转换为instancetype.你越来越依赖这种怪癖:当你写init返回id类型的时候,编译器会将它解释为返回的是instancetype型.

这些对于编译器来说是等价的:

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

在你眼中他们不等价,充其量你会忽略他们的不同并且略过它.这是你不能学会忽略的东西.


  模式

尽管init和其他方法没有区别,但是当你定义一个便利构造函数时就会有区别

这两个就不等价:

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

你想要第二种形式的.如果你的构造函数返回的是instancetype类型,你将会每次都得到正确的结果.


 一致

最后,想象一下你想要init函数,和一个便利构造函数,如果你把他们放到一起.

如果你对init使用id作返回值,你最后的代码会这样:

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

但是如果你用instancetype,代码会变成这样:

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

这会更加一致并且易读.它们的返回类型相同,并且十分明显

 

总结

除了在旧编译器上写代码,你应该适当地使用instancetype

在你写下返回值为id类型的时候你应该犹豫一下,问一下你自己:是要返回这个类的实例?如果是这样,就是instancetype类型

有很多情况是你还需要返回id类型,即如果你返回的是不同的类.

但是你应该仍然会使用instancetype类型频于id类型




0 0
原创粉丝点击