距離自己探索iOS已經過了兩個月了,現在回來重溫一下這個知識點,加深一下記憶。本次參考的有
iOS分類(category),類擴展(extension)—史上最全攻略
深入淺出理解分類(category)和類擴展(extension)
一.類別(Category)
1) 為什么要有類別?
類別存在的意義是什么?先看一下以下場景:
- 場景一(別給子類用)
有一個項目由多個開發人員同時維護著同一個類,這時候產品的需求讓A只能給當前的類Current
添加一個方法method
,但是這個Current
是個大類,有很多的子類繼承于這個類的,什么Son
、Daughter
啊之類的,如果直接粗暴地將method
貼在Current
里面,那么那些子類也就可以擁有這個方法了,這顯然不是最佳方案。
- 場景二(基于官方提供的庫來改)
有一天,一個項目里面要獲得NSString
里面是否包含敏感字符,如果我們一個個方法去加,這么多個文件,不得加到猴年馬月,就算加完了,以后又來多一個敏感字符,我的天,又多了幾個小時的工作量。
以上兩種場景都是繼承面臨的窘境,雖說繼承在面向對象編程的確給代碼的重用帶來了不少的方便,但是隨之而來的就是私有性保障
這一難關,我到底要給誰用,不能給誰用,似乎在一個超級超級大的父類中,很難去想出一個解決方案。
類別的存在,就是為以上情景應運而生的。他可以在不修改
原來類的基礎上,為一個類擴展
方法。
2) 類別不能做的事情
只能添加方法,不能添加成員變量,也就是說,如果在類別里面定義了
@property
的話,是不能使用setter
和getter
的。(其實也是可以的,但是要基于runtime來搞,在這里先不擴展)只能訪問原有類中
@protect
和@public
形式的成員變量,也就是說,@private
變量對于類別和子類來說都是一樣的,只能通過方法來訪問。
3) 同名方法調用順序
類別和原有類的命名相沖突的話,會優先調用類別里面的方法,即忽略原有類的變量,因此,同名方法調用的優先級是分類 > 本類 > 父類
,但是不建議在開發中覆蓋原有類的方法。
4) 同名多類別調用順序
如果多個類別中都有和原有類中同名的方法,則調用順序由編譯器決定,編譯器會執行最后一個參與編譯的類別方法。
二.類擴展(Extension)
類擴展是類別的一個特例,即少了分類的名稱,也可以稱為匿名分類。作用是為一個類添加一些私有
的成員變量和方法,格式如下:
@interface XXX ()
//私有屬性
//私有方法(如果不實現,編譯時會報警,Method definition for 'XXX' not found)
@end
1) 為什么要有類擴展?
一般來說,.m文件不像.h文件一樣暴露在外部,所以.m文件中聲明的方法外面是很難知道的(雖然實際上可以調用,但是這樣做很蠢),那么我們就可以把信息分為公開
和隱藏
兩種信息,把公開
的信息(變量、屬性、方法等)定義在.h文件中,而把隱藏
的信息定義在類擴展中,這樣就可以隔離接口和實現了。
所以類擴展的存在可以解決兩大問題:
定義類私有方法的地方
實現對外
readonly
,對內readwrite
的屬性,也就是說,可以在.h文件中定義一個對外是readonly
的屬性,在.m文件中的@interface
部分重新定義這個屬性是readwrite
的。實現私有變量、方法和屬性,只能被當前類訪問,則寫在類擴展里面。
2) 類擴展和類別的區別
類別中原則上只能增加方法,不能增加屬性(排除用
runtime
解決setter/geter
問題的方法)
類擴展不僅可以增加方法,還可以增加實例變量(或屬性),只是改實例變量是私有的。類別中的方法沒被實現,編譯器不會報警
類擴展中聲明的方法沒被實現,編譯器會報警(這是因為類擴展是在編譯階段被添加到類中,而類別是在運行時添加到類中)類擴展不能像類別那樣擁有獨立的實現部分(
@implementation
),也就是說,類擴展所聲明的方法必須依托在對應的類的實現部分來實現。