Chapter 4. Protocols and Categories
<br />
Item 26: Avoid Properties in Categories
<br />
這一節(jié)又說到分類里聲明屬性的問題了。
雖然在前面Item 10里講了怎樣利用associated object在分類里添加iVar并合成property的做法,但是當時也說到了,不是特殊的場景不建議這么做。這一節(jié)寫了如果直接在分類里添加屬性會發(fā)生什么。
分類自己是無法合成屬性的iVar的,只能通過Item 10中提到的方法來做。屬性的getter和setter方法也需要自己實現(xiàn),或者聲明為@dynamic,告訴編譯器在runtime再實現(xiàn)。但是因為之前也提到過,associated object是繞過了memory-management semantics和KVO的,這樣做會引起一些潛在的內存問題。
所以最穩(wěn)妥的作法還是把跟這個類相關的屬性都聲明在main interface里。
這一節(jié)最后給了一個只讀property然后自己實現(xiàn)了getter的例子,用來獲取月份名稱列表。因為在此例中并不需要iVar,所以是可以的,并且編譯器也不會抱怨,因為所需方法都自己實現(xiàn)了,編譯器就認為不用合成iVar了(對這個坑我也是踩了好幾次…)。但是這樣做和直接寫一個獲取名稱列表的方法效果上也沒什么不同,會有點舍近求遠的感覺。
<br />
Item 27: Use the Class-Continuation Category to Hide Implementation Detail
<br />
Class-continuation category這個說法在別處好像大都不這么叫,其實就是class extension。這一節(jié)講的是可以在class extension里定義什么,這樣做的好處是什么。
class extension真的是一直在用,非常熟悉。它也是分類的一種,而且是唯一一種可以合成iVar的分類。
一般在它里面定義的是只有類的內部實現(xiàn)才會用到的iVar和屬性。雖然在.h中把屬性定義為private理論上也是把屬性設置為私有了,但是有各種方法可以修改這種定義,比如我們常用的KVC。而定義在class extension里就私有化多了,雖然仍然有方法可以修改,但是還是安全多了。
當然iVar也可以直接聲明在implementation里,但是不如寫在class extension中清晰。都寫在class extension里以后,類所私有的數(shù)據(jù)就一目了然。包括類所遵守的協(xié)議,如果不想讓外界知道,或者跟外界沒有關系的,都應該放在class extension。
還有一個常用的用法是,在.h中聲明的readonly屬性,在class extension中重新聲明為readwrite,然后就可以在類內部方便地修改了,而外界原則上還是只能只讀這個屬性。這個用法在前面也提到過。
<br />
Item 28: Use a Protocol to Provide Anonymous Objects
<br />
這一節(jié)講的是id<someDelegate>這種形式的匿名對象。
這個概念是說,因為這里id可以表示任何類,所以這個對象屬于什么類這一信息是未知的,即“anonymous”,所能知道的關于這個對象的唯一信息就是它遵守了某個協(xié)議,也就是只知道它實現(xiàn)了某幾個方法。
這樣寫的原因一般由兩個,一個是想表達“在此處類型不重要”,一個是表示“在此處并不想告訴外界真正的類是什么”。
在自定義協(xié)議的時候,第一個用法很常見。一般為一個類寫完一個協(xié)議,然后會在這個類里加一個delegate屬性,這個屬性的類型就是id<someDelegate>,這里表達的意思是并不在意究竟是誰來做這個代理,只要能實現(xiàn)協(xié)議里的方法就可以。
另一個場景就是文中提到的,主觀上不想讓外界知道這個對象類型的時候。文中的例子是處理數(shù)據(jù)庫連接的一個API,其中有方法:
- (id<EOCDatabaseConnection>)connectionWithIdentifier:(NSString *)identifier;
這里返回類型是刻意被隱藏的。因為處理連接的類是多種多樣的,可以不是繼承自同一基類的,內部的實現(xiàn)可以根據(jù)情況自由選擇,但是并不想讓外界知道這些細節(jié),所以只告訴外界一個id類型,并提供一個<EOCDatabaseConnection>的協(xié)議信息,告訴外界不管使用什么類實現(xiàn)的,這個類都可以用來做連接、斷開、查詢數(shù)據(jù)庫等操作。而這個信息對外界來說已經足夠了,完全不影響對類的正常使用。而對內的安全性和私有性又得到了保障。