為什么你需要使用instancetype而不是id

原文鏈接

前言

四年前Clang添加了關(guān)鍵字instancetype,目的在于取代-alloc-init等方法的返回類型id,那么使用instancetype到底比id好在哪里?

instancetype宣言

不管何時,只要一個class要返回它相同的類實(shí)例,使用instancetype都是更加合適的。

我們知道,當(dāng)調(diào)用類中(或者子類)的-alloc、-init或者class factory(+)方法,使用instancetype關(guān)鍵字會返回它的類實(shí)例。在這種情況下用instancetype而不是id有100個好處
蘋果也這樣說:

In your code, replace occurrences of id as a return value with instancetype where appropriate. This is typically the case for init methods and class factory methods. Even though the compiler automatically converts methods that begin with “alloc,” “init,” or “new” and have a return type of id to return instancetype, it doesn’t convert other methods. Objective-C convention is to write instancetype explicitly for all methods.

更加有力的證據(jù):Adopting Modern Objective-C

為什么?

首先你可能需要知道編譯器會做什么

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

對于convenience constructor,你必須要使用instancetype,因?yàn)榫幾g器不會把id自動轉(zhuǎn)換成instancetype。

而對于initializer,當(dāng)你的代碼是這樣的:

- (id)initWithBar:(NSInteger)bar; // initializer

ARC下,編譯器會把它變成這樣:

- (instancetype)initWithBar:(NSInteger)bar; // initializer

這也是為什么有人告訴你用instancetype是沒有必要的,但是我建議你使用instancetype,原因有三:

  1. 明確性:你的代碼含義明確,絕不會做其他事。
  2. 模式化:你建立了一個良好的習(xí)慣,這確實(shí)是很重要的。
  3. 一致性:讓你的代碼更一致,并且增加可讀性。

1.明確性

在-init方法中返回instancetype確實(shí)是沒有太多的好處,這是因?yàn)榫幾g器會自動把id轉(zhuǎn)換成instancetype。

這對于編譯器來講是等價的:

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

但是至少這在你眼中是不同的。

2.模式化

雖然對init或者其他方法,返回id和instancetype沒什么不同,但是在convenient constructor(+)方法中他們是有區(qū)別的:

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

你必須要用第二條才能保證你每次運(yùn)行的結(jié)果正確,為什么?
考慮這樣的情況:


然后我們這樣調(diào)用:

發(fā)現(xiàn)x出現(xiàn)編譯警告,因?yàn)槲覀兊?factoryMethodA返回的是instancetype,它表示的是MyObject,因?yàn)镸yObject沒有-count*方法,所以出現(xiàn)了編譯警告。

然而,因?yàn)槲覀兊?factoryMethodB返回的是id,編譯器沒有在y行給警告,因?yàn)镺bjc語言動態(tài)類型和動態(tài)綁定的特性,id可能是任何class,又因?yàn)?strong>-count方法可能于存在某個類的某個地方,因此對于編譯器而言,+factoryMethodB方法返回的東西是可能實(shí)現(xiàn)-count方法的。

3.一致性

在init中可以返回id,因此你可能會這樣寫:

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

但是如果你使用instancetype,結(jié)果會是這樣:

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

這樣看起來更加一致并且可讀性更高。他們返回同樣的東西,但是后者看起來更明顯,不是嗎?

結(jié)論

當(dāng)要返回id類型的時候,你應(yīng)該思考它是否會返回一個類的實(shí)例,如果是,請使用instancetype。

參考鏈接:

  1. Why you should use instancetype instead of id

Done

作者 @biggergao

2016年05月18日

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.1 什么是自動引用計數(shù) 概念:在 LLVM 編譯器中設(shè)置 ARC(Automaitc Reference Co...
    __silhouette閱讀 5,471評論 1 17
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,554評論 19 139
  • 攢夠10000塊 能出門旅游2次 做一次飛機(jī) 去迪士尼玩一次 能找出10篇自己寫的,自己很滿意的文章 學(xué)會化妝 大...
    知易行楠閱讀 294評論 0 2
  • 人的一生,其實(shí)就是用時間和生命閱讀一本無字的書。我自詡是一個讀書人,閑暇的時候,總是手里捧著一本書,把心情埋在文字...
    古城蒼狼閱讀 418評論 5 14
  • 習(xí)慣了宅在家里不出門,不是因?yàn)閻圻@樣,只是因?yàn)楝F(xiàn)在的我很懶,比較窮。以前愛夢想,現(xiàn)在的我連理想都沒有。安安靜靜...
    孔祥聰閱讀 384評論 0 1

友情鏈接更多精彩內(nèi)容