天天看點

《編寫高品質代碼:改善Objective-C程式的61個建議》——建議5:處理隐藏的傳回類型,優先選擇執行個體類型而非id

本節書摘來自華章出版社《編寫高品質代碼:改善objective-c程式的61個建議》一 書中的第1章,第1.5節,作者:劉一道,更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

執行個體類型(instancetype)是objective-c語言中新添加的一個傳回類型,執行個體類型作為方法傳回的執行個體的類型,是蘋果在2013年的年度大會上宣布的。這個新添加的執行個體類型不僅可用來作為objective-c方法的傳回類型,且能用這個執行個體類型來作為向編譯器的提示,提示方法傳回的類型将是方法所屬的類的執行個體。

類的執行個體,作為方法傳回類型,宜采用關鍵字instancetype作為方法的傳回類型,如alloc 、init和類工廠方法等。使用instancetype作為類(或者類的子類)的執行個體傳回類型,可以大大改善objective-c代碼的類型安全。例如,考慮下面的代碼:

通過上面的代碼可以看到,instancetype作為+ factorymethoda的傳回類型,也就是說,該消息的類型表達式是myobject *。但是myobject由于先天缺乏一個-count方法,編譯器将會對此給出一個關于x行的警告:

對于這樣的情況,如果把instancetype換成id作為執行個體的方法傳回類型,也就是如上面的代碼中的執行個體,id作為類方法 + factorymethodb的傳回類型。在編譯器編譯的過程中不會發出關于y行的警告。

為什麼編譯器沒有給出警告?因為 id類型的對象可以作為任何類,并且調用的方法-count在一些類中存在,故此向編譯器發出方法+factorymethodb傳回值實作了-count的資訊,進而編譯器沒有給出警告。對于該種編寫代碼的方法,在無形中埋下了隐患。

為了確定instancetype工廠方法有正确的子類的行為,一定要使用[self class]配置設定類,而不是直接引用類名。遵循這個慣例,記住,務必要使編譯器能正确地推斷出子類類型。例如,依據前面的示例,考慮嘗試做一個前面myobject子類示例:

對于上述代碼,編譯器将會給出警告,如下面的警告:

在該示例中,+factorymethoda消息發送之後,将傳回一個類型myobjectsubclass的對象執行個體。編譯器就能恰當地确定 + factorymethoda的傳回類型應該是子類myobjectsubclass,而不是工廠方法中所聲明的超類。

在編寫代碼中,通常在處理init 方法和類工廠方法時,宜用instancetype類替換 id作為傳回值。在新版本xcode 5中,雖然,編譯器會自動地把alloc、init、new方法之中的id轉化為instancetype類型,但對于這幾種方法之外的其他方法,編譯器則不會進行轉化。在objective-c的公約之中,明确地建議對于所有方法盡可能用instancetype而非id。也就是說,作為傳回值,id由于其自身的缺陷,在objective-c中會逐漸退出,由instancetype來替代。

 僅有在作為傳回值時,宜用instancetype來替換id,而不是代替代碼中所有id。與id不同,instancetype關鍵字僅能作為方法聲明的傳回類型。也就說,在某一個特定區域,instancetype可以替代id,并非所有區域都可以替代id。

例如:

 要點

(1)instancetype僅僅用來作為objective-c方法的傳回類型。

(2)使用instancetype可避免隐式轉換id而造成的欺騙性編譯無誤通過的現象,防止程式正式運作時出現崩潰現象,可以大大改善objective-c代碼的類型安全。

(3)在某一個特定區域,instancetype可以替代id,并非所有區域都可以替代id。

繼續閱讀