instancetype vs id for Objective-C

来源:互联网 发布:网络机顶盒如何更新 编辑:程序博客网 时间:2024/05/22 16:39

Why you should use instancetype instead of id

In my previous entry, I discussed when id will be promoted toinstancetype. But now that I’ve explained this, I’d like to explain why you should understand this but not rely on it. Instead, you should useinstancetype directly.

Let me start with this bold statement, then I’ll back up and explain it: Use instancetype whenever it’s appropriate, which is whenever a class returns an instance of that same class.

First, some definitions:

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

For a convenience constructor, you should always useinstancetype. The compiler does not automatically convert id toinstancetype.

For initializer, it’s more complicated. When you type this:

- (id)initWithBar:(NSInteger)bar

…the compiler will pretend you typed this instead:

- (instancetype)initWithBar:(NSInteger)bar

This was necessary for ARC. This is why people will tell you it isn’t necessary to use instancetype, though I contend you should. The rest of this answer deals with this.

There’s three advantages:

  1. Explicit. Your code is doing what it says, rather than something else.
  2. Pattern. You’re building good habits for times it does matter, which do exist.
  3. Consistency. You’ve established some consistency to your code, which makes it more readable.

Explicit

It’s true that there’s no technical benefit to returning instancetypefrom an init. But this is because the compiler automatically converts the id to instancetype. You are relying on this quirk; while you’re writing that the init returns an id, the compiler is interpreting it as if it returns an instancetype.

These are equivalent to the compiler:

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

These are not equivalent to your eyes. At best, you will learn to ignore the difference and skim over it. This is not something you should learn to ignore.

Pattern

While there’s no difference with init and other methods, there is a different as soon as you define a convenience constructor.

These two are not equivalent:

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

You want the second form. If you are used to typing instancetype as the return type of a constructor, you’ll get it right every time.

Consistency

Finally, imagine if you put it all together: you want an init function and also a convenience constructor.

If you use id for init, you end up with code like this:

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

But if you use instancetype, you get this:

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

It’s more consistent and more readable. They return the same thing, and now that’s obvious.

Conclusion

Unless you’re intentionally writing code for old compilers, you should use instancetype when appropriate.

You should hesitate before writing a message that returns id. Ask yourself: Is this returning an instance of this class? If so, it’s aninstancetype.

There are certainly cases where you need to return id; namely, if you’re returning a different class. But you’ll probably use instancetypemuch more frequently than id.


链接:http://tewha.net/2013/02/why-you-should-use-instancetype-instead-of-id/

/*******************************************************************/

instancetype vs id for Objective-C

新的LLVM编译器为我们带来了ARC, Object Literal and Scripting, Auto Synthesis等特性,同时也引入了instancetype关键字。instancetype用来表示Related Result Types(相关返回类型),那么它与id有什么不同呢?

根据Cocoa的命名惯例,init, alloc这类的方法,如果以id作为返回类型,会返回类本身的类型。

123
@interface Person- (id)initWithName:(NSString *)name;+ (id)personWithName:(NSString *)name;

但类方法的返回类型,LLVM(或者说Clang)却无法判断,我们来看一段代码:

123
// You may get two warnings if you're using MRC rather than ARC[[[NSArray alloc] init] mediaPlaybackAllowsAirPlay]; // ❗ "No visible @interface for `NSArray` declares the selector `mediaPlaybackAllowsAirPlay`"[[NSArray array] mediaPlaybackAllowsAirPlay]; // It's OK. But You'll get a runtime error instead of a compile time one

[NSArray array]除非显式转换为(NSArray *),否则编译器不会有错误提示。如果使用instancetype就不会有这样的问题:

123
@interface Person- (instancetype)initWithName:(NSString *)name;+ (instancetype)personWithName:(NSString *)name;

简单来说,instancetype关键字,保证了编译器能够正确推断方法返回值的类型。这种技术基本从iOS 5的UINavigationController里就开始应用了。

Clang的文档里提到instancetype is a contextual keyword that is only permitted in the result type of an Objective-C method. 也就是说,instancetype只能作为返回值,不能像id那样作为参数。

链接:http://www.iwangke.me/2013/01/06/instancetype-vs-id-for-objective-c/

/*****************************************************************/

0 0
原创粉丝点击