標籤:
目錄(?)[-]
- 有一個相同兩個不同相同
- Written by Mattt Thompson on Dec 10th 2012
- 一什麼是instancetype
- 二關聯傳回型別related result types
- 三instancetype作用
- 作用
- 好處
- 四instancetype和id的異同
- 相同點
- 不同點
有一個相同兩個不同。相同Written by Mattt Thompson on Dec 10th, 2012
Objective-C is a rapidly evolving language, in a way that you just don‘t see in established programming languages. ARC, object literals, subscripting, blocks: in the span of just three years, so much of how we program in Objective-C has been changed (for the better).
All of this innovation is a result of Apple‘s philosophy of vertical integration. Just as Apple‘s investment in designing its own chipsets gave them leverage to compete aggressively with their mobile hardware, so too has their investment in LLVM allowed their software to keep pace.
Clang developments range from the mundane to paradigm-changing, but telling the difference takes practice. Because we‘re talking about low-level language features, it‘s difficult to understand what implications they may have higher up with API design.
One such example is instancetype
, the subject of this week‘s article.
In Objective-C, conventions aren‘t just a matter of coding best-practices, they are implicit instructions to the compiler.
For example, alloc
and init
both have return types of id
, yet in Xcode, the compiler makes all of the correct type checks. How is this possible?
In Cocoa, there is a convention that methods with names like alloc
, or init
always return objects that are an instance of the receiver class. These methods are said to have a related result type.
Class constructor methods, although they similarly return id
, don‘t get the same type-checking benefit, because they don‘t follow that naming convention.
You can try this out for yourself:
[[[NSArray alloc] init] mediaPlaybackAllowsAirPlay]; // ? "No visible @interface for `NSArray` declares the selector `mediaPlaybackAllowsAirPlay`"[[NSArray array] mediaPlaybackAllowsAirPlay]; // (No error)
Because alloc
and init
follow the naming convention for being a related result type, the correct type check against NSArray
is performed. However, the equivalent class constructor array
does not follow that convention, and is interpreted as id
.
id
is useful for opting-out of type safety, but losing it when you do want it sucks.
The alternative, of explicitly declaring the return type ((NSArray *)
in the previous example) is a slight improvement, but is annoying to write, and doesn‘t play nicely with subclasses.
This is where the compiler steps in to resolve this timeless edge case to the Objective-C type system:
instancetype
is a contextual keyword that can be used as a result type to signal that a method returns a related result type. For example:
@interface Person+ (instancetype)personWithName:(NSString *)name;@end
instancetype
, unlike id
, can only be used as the result type in a method declaration.
With instancetype
, the compiler will correctly infer that the result of +personWithName:
is an instance of a Person
.
Look for class constructors in Foundation to start using instancetype
in the near future. New APIs, such as UICollectionViewLayoutAttributes are using instancetype
already.
下面的翻譯:原文地址:http://blog.csdn.net/wzzvictory/article/details/16994913
一、什麼是instancetype
instancetype是clang 3.5開始,clang提供的一個關鍵字,表示某個方法返回的未知類型的Objective-C對象。我們都知道未知類型的的對象可以用id關鍵字表示,那為什麼還會再有一個instancetype呢?
二、關聯傳回型別(related result types)
根據Cocoa的命名規則,滿足下述規則的方法:
1、類方法中,以alloc或new開頭
2、執行個體方法中,以autorelease,init,retain或self開頭
會返回一個方法所在類類型的對象,這些方法就被稱為是關聯傳回型別的方法。換句話說,這些方法的返回結果以方法所在的類為類型,說的有點繞口,請看下面的例子:
[objc] view plaincopy
- @interface NSObject
- + (id)alloc;
- - (id)init;
- @end
-
- @interface NSArray : NSObject
- @end
當我們使用如下方式初始化NSArray時:
[objc] view plaincopy
- NSArray *array = [[NSArray alloc] init];
按照Cocoa的命名規則,語句[NSArray alloc] 的類型就是NSArray*因為alloc的傳回型別屬於關聯傳回型別。同樣,[[NSArray alloc]init] 的返回結果也是NSArray*。
三、instancetype作用1、作用
如果一個不是關聯傳回型別的方法,如下:
[objc] view plaincopy
- @interface NSArray
- + (id)constructAnArray;
- @end
當我們使用如下方式初始化NSArray時:
[objc] view plaincopy
- [NSArray constructAnArray];
根據Cocoa的方法命名規範,得到的傳回型別就和方法聲明的傳回型別一樣,是id。
但是如果使用instancetype作為傳回型別,如下:
[objc] view plaincopy
- @interface NSArray
- + (instancetype)constructAnArray;
- @end
當使用相同方式初始化NSArray時:
[objc] view plaincopy
- [NSArray constructAnArray];
得到的傳回型別和方法所在類的類型相同,是NSArray*!
總結一下,instancetype的作用,就是使那些非關聯傳回型別的方法返回所在類的類型!
2、好處
能夠確定對象的類型,能夠協助編譯器更好的為我們定位代碼書寫問題,比如:
[objc] view plaincopy
- [[[NSArray alloc] init] mediaPlaybackAllowsAirPlay]; // "No visible @interface for `NSArray` declares the selector `mediaPlaybackAllowsAirPlay`"
-
- [[NSArray array] mediaPlaybackAllowsAirPlay]; // (No error)
上例中第一行代碼,由於[[NSArray alloc]init]的結果是NSArray*,這樣編譯器就能夠根據返回的資料類型檢測出NSArray是否實現mediaPlaybackAllowsAirPlay方法。有利於開發人員在編譯階段發現錯誤。
第二行代碼,由於array不屬於關聯傳回型別方法,[NSArray array]返回的是id類型,編譯器不知道id類型的對象是否實現了mediaPlaybackAllowsAirPlay方法,也就不能夠替開發人員及時發現錯誤。
四、instancetype和id的異同1、相同點
都可以作為方法的傳回型別
2、不同點
①instancetype可以返回和方法所在類相同類型的對象,id只能返回未知類型的對象;
②instancetype只能作為傳回值,不能像id那樣作為參數,比如下面的寫法:
[objc] view plaincopy
- //err,expected a type
- - (void)setValue:(instancetype)value
- {
- //do something
- }
就是錯的,應該寫成:
[objc] view plaincopy
- - (void)setValue:(id)value
- {
- //do something
- }
Objective-C中的instancetype和id區別