分類(類別/Category)與 類擴展(Extension)


一、分類(類別/Category)

1、適用范圍

     當你已經封裝好了一個類(也可能是系統類、第三方庫),不想在改動這個類了,可是隨着程序功能的增加需要在類中增加一個方法,這時我們不必修改主類,只需要給你原來的類增加一個分類。
     將一個大型的類拆分成不同的分類,在不同分類中實現類別聲明的方法,這樣可以將一個類的實現寫到多個.m文件中,方便管理和協同開發。
     分類中的方法可以只聲明,不實現,所以在協議不支持可選方法的時候(協議現在已經支持可選方法),通常把分類作為非正式協議使用。
 
2、語法格式
     文件中的語法
@interface 主類類名(分類類名)
//不可以定義成員屬性
@end

@implementation 主類類名(分類類名)

@end

 

     文件名通常為:主類名+分類名

     調用方法時,只需要向主類引用發送消息即可。
 
3、注意事項
  • 分類中方法的優先級比原來類中的方法高,也就是說,在分類中重寫了原來類中的方法,那么分類中的方法會覆蓋原來類中的方法
  • 分類中只能聲明方法,不能添加屬性變量,在運行時分類中的方法與主類中的方法沒有區別
  • 通常來講,分類定義在.h文件中,但也可以定義.m文件中,此時分類的方法就變成私有方法
4、如何使用
     定義PYJViewController類的分類
     “ PYJViewController+Category Controller.h”文件:
@interface PYJViewController (CategoryController)
- (void)test;
@end

    “PYJViewController+CategoryController.m”文件:

@implementation PYJViewController (CategoryController)
- (void)test {
     NSLog(@"這是一個分類");
}
@end

 

5、雖然不能在分類(類別)中定義成員屬性,但是有辦法也可以讓它支持添加屬性和成員變量

    Category是Objective-C中常用的語法特性,通過它可以很方便的為已有的類來添加函數。但是Category不允許為已有的類添加新的屬性或者成員變量。     
    一種常見的辦法是通過runtime.h中objc_getAssociatedObject / objc_setAssociatedObject來訪問和生成關聯對象。通過這種方法來模擬生成屬性。

    “NSObject+SpecialName.h”文件:

@interface NSObject (SpecialName)
@property (nonatomic, copy) NSString *specialName;
@end

    “NSObject+SpecialName.m”文件:

#import "NSObject+Extension.h"
#import <objc/runtime.h>
static const void *SpecialNameKey = &SpecialNameKey;    
@implementation NSObject (SpecialName)
@dynamic specialName;

- (NSString *)specialName {
    //如果屬性值是非id類型,可以通過屬性值先構造OC的id對象,再通過對象獲取非id類型屬性
    return objc_getAssociatedObject(self, SpecialNameKey);
}

- (void)setSpecialName:(NSString *)specialName{
    //如果屬性值是非id類型,可以通過屬性值先構造OC的id對象,再通過對象獲取非id類型屬性
    objc_setAssociatedObject(self, SpecialNameKey, specialName, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 

@end

 

 

 

二、類擴展

1、適用范圍

     擴展是分類的一種特殊形式。
 
2、語法格式
     @interface 主類類名()
     @end
     擴展通常定義在 主類.m文件中,擴展中聲明的方法直接在 主類.m文件中實現。
 
3、注意事項
  • 擴展中可以聲明實例變量,可以聲明屬性
  • 因為擴展通常定義在主類的.m文件中,所以擴展聲明的方法和屬性通常是私有的
4、分類和擴展的區別
     分類是不可以聲明實例變量,通常是公開的,文件名是:主類名+分類名.h
     擴展是可以聲明實例變量,是私有的,文件名為:主類名_擴展標識.h,在主類的.m文件中#import該頭文件
 
5.如何使用
    定義 PYJViewController類的擴展
    方式1、以單獨的文件定義
    “PYJViewController_ExtensionController.h ”文件:
#import"PYJViewController.h"

@interface PYJViewController ()
@property(nonatomic, copy)NSString *stringExtension;
- (void)testExtension;
@end

 

    方式2、在主類的.m文件中定義

    “PYJViewController.m”文件:

#import"PYJViewController.h"

@interface PYJViewController ()
@property(nonatomic, copy)NSString *stringExtension;
- (void)testExtension;
@end

    在主類的.m文件中實現擴展定的方法:

@implementation PYJViewController
- (void)testExtension {
   self.stringExtension = @"給擴展里面定義的屬性字符串賦值";
   NSLog(@"定義的屬性String是:%@", self.stringExtension);
}
@end

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM