OC基礎8:分類和協議

1、關於分類(category):

(1)、分類用來拓展現有的類,增加方法,同時可以不必訪問主類的源代碼,也不用創建子類;

(2)、只能增加方法,不能增加變量;

(3)、在代碼中也只需要import進父類的h文件,不能編寫任何繼承的語法,因爲不是子類;

(4)、在分類裏添加的新方法會被子類繼承。


2、編寫一個分類的模板:

原類是MyClass,分類的名稱是MyClass+Cate,那麼模板如下:

   #import “MyClass.h”

   @interface MyClass (Cate)

     …   //各種方法

   @end

   其中要注意:import文件使用的是雙引號,@interface後面沒有繼承的冒號,緊跟着用括號聲明這個分類的名稱。可用下面的圖片來說明:

 

3、

分類的m文件的內容可以寫在主類的m文件裏面。

比如Class和ClassCateClass可以共用一個Class.m文件。也可以各自分開爲Class.m文件和ClassCateClass.m文件,如果分開的話, ClassCateClass.m文件應該這樣寫:

 #import “ClassCateClass.h”

 @implementation Class (CateClass)

   …

 @end

 

4、由3也可以看到,分類的h文件和m文件的命名方式。直接用主類名稱加上分類名稱來命名,比如Class+CateClass.h,或者可以是ClassCateClass.h;

 

5、擴展(extension):類的擴展是一種特殊的分類,是沒有命名的分類。擴展可以定義新的實例變量和屬性,這在分類裏是不允許的。它的定義語法和分類基本一樣,區別只是在括號裏不需要寫出名稱,保持空即可。即是只要在類名後加一對括號即可。

 

6、擴展類的方法是私有的,即是它定義的數據和方法只供這個類本身使用。

 

7、擴展類的@interface部分最好寫在主類的m文件裏,保持代碼良好的封裝性。

 

8、要添加額外方法,分類(category)必須在第一個@interface中聲明方法,並且在@implementation中提供實現,不然運行時會出錯。而類擴展(extension)中添加的方法可以不在第一個@interface中去聲明,而且沒有必要在擴展裏添加方法,因爲擴展裏聲明的方法是私有方法,而不需聲明只定義在@implementation中的方法就是私有方法了。

 

9、分類可以覆寫主類的方法,不過覆寫之後就再也不能訪問原來的方法了,因爲它們不是父類子類的關係,無法通過super關鍵字來訪問。所以如果要覆寫方法,或者使用子類,或者要先小心地把主類方法中的所有功能複製到覆寫的方法裏。

 

10、協議:協議是一串方法的列表,只有方法名,沒有方法的具體實現。當某些類遵守某個協議之後,在類裏面纔會去具體地定義協議包括的這些方法。當某一個類聲明遵守了某項協議之後,我們就可以在不知曉這個類的源代碼的情況下,通過協議規定的方法來訪問這個類。

 

11、協議使用@protocol指令和@end指令來定義,在這兩者之間僅僅需要聲明一些方法即可。聲明的方法默認是@required類型的,即是遵守這個協議的類必須去實現的。如果有一些選擇實現的方法,使用@optional去定義。模板如下,定義在h文件內:

@protocol Xprotoc

…   //方法列表名,聲明在這裏的方法是遵守這個協議的類必須要實現的

  @optional   //從這個關鍵字開始,下方的方法列表是不強制要求實現的

  …   //不強制要求實現的方法列表

  @required   //從這個關鍵字開始,下方的方法列表又是必須要實現的了

  …   //要求必須實現的方法列表

@end

 

12、聲明某個類XCalss遵守某個協議XProtoc的模板如下:

@interface XClass: Nobject <XProtocol>

尖括號內可以列出多個協議,使用逗號分開即可。

 

13、如果有一個對象xClass,想要測試它是否遵循了XProtoc協議,可以使用以下方法:

if ([xClass conformsToProtocol: @protocol (XProtoc)] == YES) {

  ...

}

 

14、使用id類型聲明對象時,使用以下命令:

id <XProtoc> xClass;

那麼當程序爲xClass指定靜態類型的對象的時候,如果這個對象不遵循XProtoc協議,編譯器就會提示警告。尖括號內可以用逗號隔開多個協議,表示這個動態對象必須遵循多個協議。

 

15、協議也可以像類一樣進行擴展,方法即是在聲明一個新的協議的時候,使用尖括號讓它必須遵循舊的某個協議,效果其實就是舊協議的擴展。如下:

@protocol NewProtoc <XProtoc>

那麼任何採用NewProtoc協議的類都必須要同時遵循NewProtoc協議和XProtoc協議。

 

16、分類也可以採用某項協議,如下:

    @interface XClass (CateClass) <NewProtoc>

 

17、如果你不想公開在h文件中聲明你的類遵循的協議,那麼你也可以把採用某些協議的語句(@interface語句,參照擴展類)寫在m文件裏,如下:

@interface XClass () < NewProtoc >

  ...

@end

 

18、定義了協議的類可以看做是把協議裏定義的方法代理(delegate)給了實現它們的類。Cocoa和iOS非常依賴代理這個概念。

 

19、關於合成對象

有時子類繼承了父類之後,同時也繼承了一些子類不需要或者有衝突的方法。比如Square類繼承自Rectangle類,也繼承了Rectangle類設置長和寬的方法,但是對於Square類來說只需要設置一個邊長,繼承來的設置長和寬的方法並不適用,如果有對象不小心調用了父類繼承來的這個設置長和寬的方法,反而會出現錯誤。

那麼這時可以採取另一種處理方法:定義一個新類,然後不要讓這個新類繼承舊類,而是在這個新類中包含一個或多個它本來要繼承的舊類的對象。

這種新類的對象就是合成對象,因爲它是由其他對象組成的。比如以下的例子:

@interface Square: NSObject {

  Rectangle *rect;

}

-(int) setSide: (int) s;

...

@end

注意這個Square類就不是Rectangle類的子類了,子類的對象是可以直接訪問父類的方法的,而在這個例子中,Square類的對象就沒法直接訪問Rectangle類的方法了。

這時要通過Square類的對象要訪問Rectangle類的方法就必須受到Square類的限制了,比如假設Rectangle類有一個方法-(int) area,那麼在Square類裏面可以這麼定義:

-(int) area {

  return [rect area];

}

那麼要訪問Rectangle類的方法就只能通過Square類提供的area方法,實現了監控。但是要注意在合成對象的初始化的時候記得也要爲這個內部的對象rect做初始化。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章