天天看點

分類,類别,類擴充

首先,介紹一個簡單的概念,分類=類别=Category。 

分類(Category):

概念: 分類(Category)是OC中的特有文法,它是表示一個指向分類的結構體的指針。可以給某一個類擴充一些方法(不修改原來類的代碼),原則上它隻能增加方法,不能增加成員(執行個體)變量。具體原因看源碼組成:

Category源碼:

typedef struct objc_category *Category;
struct objc_category {
  char *category_name                          OBJC2_UNAVAILABLE; // 分類名
  char *class_name                             OBJC2_UNAVAILABLE; // 分類所屬的類名
  struct objc_method_list *instance_methods    OBJC2_UNAVAILABLE; // 執行個體方法清單
  struct objc_method_list *class_methods       OBJC2_UNAVAILABLE; // 類方法清單
  struct objc_protocol_list *protocols         OBJC2_UNAVAILABLE; // 分類所實作的協定清單
}
           

通過上面我們可以發現,這個結構體主要包含了分類定義的執行個體方法與類方法,其中instance_methods 清單是 objc_class 中方法清單的一個子集,而class_methods清單是元類方法清單的一個子集。 但這個結構體裡面

根本沒有屬性清單, 根本沒有屬性清單, 根本沒有屬性清單。

注意: 

1.分類是用于給原有類添加方法的,因為分類的結構體指針中,沒有屬性清單,隻有方法清單。是以< 原則上講它隻能添加方法, 不能添加屬性(成員變量),實際上可以通過其它方式添加屬性> ;   

2.分類中的可以寫@property, 但不會生成setter/getter方法, 也不會生成實作以及私有的成員變量(編譯時會報警告); 

3.可以在分類中通路原有類中.h中的屬性; 

4.如果分類中有和原有類同名的方法, 會優先調用分類中的方法, 就是說會忽略原有類的方法。是以同名方法調用的優先級為 分類 > 本類 > 父類。是以在開發中盡量不要覆寫原有類; 

5.如果多個分類中都有和原有類中同名的方法, 那麼調用該方法的時候執行誰由編譯器決定;編譯器會執行最後一個參與編譯的分類中的方法。

類擴充

這個東西每天都要見,但是大多數人不在意它

這是一個類的.m檔案

#import "ZDMessageViewController.h"

@interface ZDMessageViewController ()
@property(nonatomic,strong) NSMutableArray *allDataMutableArray;
@end
           

這個東西就叫做類擴充,可以為一個類添加一些私有的成員變量和方法,其方法也在.m中實作

分類與類擴充的差別:

①類别中原則上隻能增加方法(能添加屬性的的原因隻是通過runtime解決無setter/getter的問題而已);

②類擴充不僅可以增加方法,還可以增加執行個體變量(或者屬性),隻是該執行個體變量預設是@private類型的( 用範圍隻能在自身類,而不是子類或其他地方);

③類擴充中聲明的方法沒被實作,編譯器會報警,但是類别中的方法沒被實作編譯器是不會有任何警告的。這是因為類擴充是在編譯階段被添加到類中,而類别是在運作時添加到類中。

④類擴充不能像類别那樣擁有獨立的實作部分(@implementation部分),也就是說,類擴充所聲明的方法必須依托對應類的實作部分來實作。

⑤定義在 .m 檔案中的類擴充方法為私有的,定義在 .h 檔案(頭檔案)中的類擴充方法為公有的。類擴充是在 .m 檔案中聲明私有方法的非常好的方式。