蘋(píng)果在iOS 8中全面使用instancetype代替id
Steven Fisher:只要一個(gè)類(lèi)返回自身的實(shí)例,用instancetype就有好處。
@interface
Foo:
NSObject
-
(
id
)
initWithBar
:(
NSInteger
)
bar
;
// initializer
+
(
id
)
fooWithBar
:(
NSInteger
)
bar
;
// convenience constructor
@end
對(duì)于簡(jiǎn)易構(gòu)造函數(shù)(convenience constructor),應(yīng)該總是用instancetype。編譯器不會(huì)自動(dòng)將id轉(zhuǎn)化為instancetype。id是通用對(duì)象,但如果你用instancetype,編譯器就知道方法返回什么類(lèi)型的對(duì)象。
這個(gè)問(wèn)題可不只有學(xué)術(shù)意義,比如,[[NSFileHandle fileHandleWithStandardOutput] writeData:formattedData]在Mac OS X(只在該OS版本)中會(huì)報(bào)錯(cuò)“Multiple methods named 'writeData:' found with mismatched result, parameter type or attributes.”原因是NSFileHandle和NSURLHandle都提供writeData:方法。由于[NSFileHandle fileHandleWithStandardOutput] 返回的類(lèi)型是id,編譯器并不確定請(qǐng)求了哪個(gè)類(lèi)的writeData:方法。
你可以用
[(
NSFileHandle
*
)[
NSFileHandle
fileHandleWithStandardOutput
]
writeData
:
formattedData
];
或
NSFileHandle
*
fileHandle
=
[
NSFileHandle
fileHandleWithStandardOutput
];
[
fileHandle
writeData
:
formattedData
];
來(lái)繞過(guò)。
當(dāng)然,更好的方法是聲明fileHandleWithStandardOutput的返回類(lèi)型為instancetype。(注意:這段樣例代碼在iOS中并不會(huì)報(bào)錯(cuò),因?yàn)閕OS中只有NSFileHandle提供writeData:方法。但length等方法則會(huì),UILayoutSupport會(huì)返回CGFloat,而NSString則會(huì)返回NSUInteger)
initializer的情況更復(fù)雜,當(dāng)你輸入
-
(
id
)
initWithBar:
(
NSInteger
)
bar
編譯器會(huì)假設(shè)你輸入了
-
(
instancetype
)
initWithBar:
(
NSInteger
)
bar
對(duì)于ARC而言,這是必須的。 Clang Language Extensions 的相關(guān)結(jié)果類(lèi)型(Related result types)也講到了這一點(diǎn)。也許別人會(huì)據(jù)此告訴你不必使用instancetype,但我建議你用它。下面解釋我為什么如此建議。
使用instancetype有三點(diǎn)好處:
1、明確性。代碼只做你讓它做的事,而不是其他。
2、程式化。你會(huì)養(yǎng)成好習(xí)慣,這些習(xí)慣在某些時(shí)候會(huì)很有用,而且肯定有用武之地。
3、一致性。讓代碼可讀性更好。
明確性
用instancetype代替id作為返回值的確沒(méi)有 技術(shù)上的好處 。但這是因?yàn)榫幾g器自動(dòng)將id轉(zhuǎn)化成了instancetype。你以為init返回的值類(lèi)型是id,其實(shí)編譯器返回了instancetype。
這兩行代碼對(duì)于編譯器來(lái)說(shuō)是 一樣 的:
-
(
id
)
initWithBar:
(
NSInteger
)
bar
;
-
(
instancetype
)
initWithBar:
(
NSInteger
)
bar
;
但在你眼里,這兩行代碼卻不同。你不該學(xué)著忽視它。
模式化
在使用init等方法時(shí)的確沒(méi)有區(qū)別,但在定義簡(jiǎn)易構(gòu)造函數(shù)時(shí)就有區(qū)別了。
這兩行代碼并不等價(jià):
+
(
id
)
fooWithBar:
(
NSInteger
)
bar
;
+
(
instancetype
)
fooWithBar:
(
NSInteger
)
bar
;
如果用instancetype作為函數(shù)的返回類(lèi)型,就不會(huì)出錯(cuò)。
一致性:
最后,想象把所有東西放到一起時(shí)的情景:你想要一個(gè)init方法和一個(gè)簡(jiǎn)易構(gòu)造函數(shù)。
如果你用id來(lái)作為init函數(shù)的返回類(lèi)型,最終代碼如下:
-
(
id
)
initWithBar:
(
NSInteger
)
bar
;
+
(
instancetype
)
fooWithBar:
(
NSInteger
)
bar
;
但如果你用instancetype,代碼如下:
-
(
instancetype
)
initWithBar:
(
NSInteger
)
bar
;
+
(
instancetype
)
fooWithBar:
(
NSInteger
)
bar
;
代碼更加一致,可讀性更強(qiáng)。它們返回相同的東西,這一點(diǎn)一目了然。
結(jié)論
除非你有意為舊編譯器寫(xiě)代碼,不然你在合適的時(shí)候都應(yīng)該用instancetype。
在寫(xiě)一條返回id的消息前,問(wèn)自己:這個(gè)類(lèi)返回實(shí)例嗎?如果返回,用instancetype。
肯定有需要返回id的時(shí)候,但你用instancetype的頻率應(yīng)該會(huì)更高。
本答案摘自:http://zhuanlan.zhihu.com/Foundation/19569459
原帖: objective c - Would it be beneficial to begin using instancetype instead of id?
注意:我也是剛?cè)腴T(mén)而已,如果翻譯的術(shù)語(yǔ)與通行術(shù)語(yǔ)不一致,敬請(qǐng)告知;如果選取的翻譯內(nèi)容有誤或過(guò)時(shí),敬請(qǐng)告知,謝謝。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
