Objective-C中的類目(Category),延展(Extension),協定(Protocol)這些名詞看起來挺牛的,瞬間感覺OC好高大上。在其他OOP語言中就沒見過這些名詞,剛看到這三個名詞的時候,有種感覺這是不是學習的坎?這東西難不難?能不能學會?經過本人親自驗證,這三個東西了解起來還是蠻簡單的,學過C++或者Java的小夥伴對比了解還是蠻輕松的。類目(Category)就是給已有的類擴充相應的方法,擴充的方法是公有的,類目還可以起到分子產品的功能,下面會詳細說到。 延展(Extension)這個名詞就是是匿名類目的别稱,匿名類目就叫做延展,延展可以實作類方法的私有化,具體如何實作,下面有源碼。協定我個人感覺和Java中的接口極為相似,在定義對象時使用協定,個人感覺和Java中得泛型有着異曲同工之妙,看下文的詳細介紹吧。(本文為筆者個人總結,歡迎批評指正)。
一.Objective-C中的類目(Category)
在Objective-C比其他OOP的程式設計語言多了個類目,在OC中除了用繼承來擴充類的功能函數外我們還可以用類目來實作。學過C++的小夥伴們是否還記得友元這個概念呢?友元就是非本類的方法可以使用本類中得變量,這也是對類方法的一個擴充,個人感覺在OC中得類目和C++中的友元有着異曲同工之妙(僅代表個人觀點,歡迎批評指正),下面我們就來詳細的學習一下OC中得類目吧。
提到類目呢,首先我們會問我們具體能拿類目做些什麼事情呢下面做一下總結:
1.可以用類目給已有的類擴充方法
2.可以用類目把類的實作按功能子產品分為不同的檔案
3.可以用來擴充NSObject類的方法,也叫做非正式協定
編譯環境說明: iMac OS X 10.9 (13A603) 編譯器:XCode 5.0.2版本
1.給已有的類擴充方法
在Xcode中建立CategoryTest類,在建立類中聲明兩個執行個體變量,在實作類中重寫description方法,列印輸出兩個執行個體變量的值
代碼如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
建立一個CategoryTest的類目,來進行對類方法的擴充,
代碼如下:
|
實作檔案:
|
測試運作結果:
|
2.對把類中不同的功能子產品分成不同的檔案
1.給上面的類建立兩個類目,類目中分别存放執行個體變量的getter和setter方法,為了節省篇幅下面給出其中一個類目的事例;
接口的聲明:
|
類目的實作檔案:
|
對代碼測試的結果:
|
3.非正式協定
非正式協定就是給NSObject類建立的類目又叫做非正式協定, 非正式協定一般不需要進行實作,一般在子類中進行方法的重寫。代碼在這就不贅述啦!
類目的優缺點分析(下面有些是個人觀點,不對之處請批評指正)
優點:上面的功能也是類目存在的重要原因之所在,在這就不重複了
局限性: 在類目中隻可以為類添加方法,不能添加執行個體變量; 類目中得方法的優先級要高。
二.Objective-C中的延展(Extension)
簡單的說匿名類目就是延展,在延展中定義的方法是類私有的方法隻能在類的内部調用,定義延展的方式就是把類目中括号中得名字省略掉,括号保留這就是延展。其實在延展中定義的方法不是真正的私有方法和C++, Java中得方法還有所差別,在類初始化的檔案中引入相應延展的頭檔案,其延展對應的方法也是可以通路的。是通過隐藏延展的頭檔案來達到方法私有 的。
定義私有方法有以下三種方式:
1.通過延展來實作方法的私有,延展的頭檔案獨立。這種方法不能實作真正的方法私有,當在别的檔案中引入延展的頭檔案,那麼在這個檔案中定義的類的對象就可以直接調用在延展中定義所謂私有的方法。demo如下:
代碼如下:
延展相應的頭檔案,延展方法的實作在類對應的.m中給出實作方法:
|
2.第二種實作延展的方式是延展沒有獨立的頭檔案,在類的實作檔案.m中聲明和實作延展,這種方法可以很好的實作方法的私有,因為在OC中是不能引入.m的檔案的
3.第三種實作方法私有的方式是在.m檔案中得@implementation中直接實作在@interface中沒有聲明的方法,這樣也可以很好的實作方法的私有。
Extension.m中的代碼
23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
在main函數裡進行測試,如果在main函數裡引入#import "ExtensionTest_Extension1.h"也可以調用其裡面聲明的相應的方法
測試代碼如下:
|
運作結果:
|
三、Objective中得協定Protocol
協定(protocol)提到OC中得協定個人感覺和JAVA中的接口的用法極為相似。把類中常用的方法抽象成OC中得協定,協定中隻有方法的聲明沒有方法的實作,在protocol中可以把方法定義成@required(必須的):在使用協定的類中如果不實作@required的方法,編譯器不會報錯但會給出警告。還可以把protocol中的方法定義成@optional(可選的)如果在使用協定的類中不實作@optional方法,則不會警告。協定的關鍵字用@protocol來定義。
下面是協定的一個簡單demo;
1.在Xcode中建立一個Protocol,命名為FirstProtocol,檔案名為FirstProtocol.h . 在FirstProtocol協定中聲明了兩個方法,一個是@required一個是@optional的
|
2.建立一個類命名為ProtocolClass, 在ProtocolClass.h中使用FirstProtocol協定,在ProtocolClass.m檔案中實作協定中得方法
ProtocolClass.h的代碼如下:
|
ProtocolClass.m的代碼如下:
|
測試的運作結果為:
|
在聲明對象的時候引入協定可以類比這Java中得泛型來學習, 例如聲明一個遵守FirstProtocol協定的對象: id<FirstProtocol> obj;下面我們将用一個事例來介紹具體的用法
1.建立一個CalculatorProtocol的協定,在協定中聲明一個calculatorFunction的方法來進行兩個數的計算,檔案名為:calculatorProtocol.h
代碼如下:
|
2.在CalculatorClass類中添加新的方法,在這個類中有一個計算方法,需要對兩個數的計算,有一個參數是對象類型的必須遵循協定CalculatorProtocol,主要代碼如下:
|
3.定義遵循協定calculatorProtocol的類AddClass,在AddClass中實作calculatorFunction方法,實作兩個數相加的功能代碼如下
|
4.建立一個DecClass類,同樣遵循calculatorProtocol協定,實作兩個數相減的功能,主要代碼如下:
|
測試代碼:
|
運作結果如下:
|
再舉一個了解協定更好了解協定的例子吧,我們聲明一個檔案協定,協定的内容是對檔案的讀和寫。我們在聲明一個檔案管理系統的類,隻要是檔案能讀和寫就能放進我們的檔案管理系統進行管理。
1.指定可放入檔案管理系統檔案需要遵循的協定,協定中規定檔案必須有讀寫的功能
代碼如下
#import <Foundation/Foundation.h>
@protocol FileManagerProtocol <NSObject>
//讀方法
-(void) read;
//寫方法
-(void) writer;
@end
2.編寫檔案管理系統,來對所有遵守協定的檔案來進行的統一的管理
代碼如下:
聲明:
#import <Foundation/Foundation.h>
#import "FileManagerProtocol.h"
@interface FileManagerSystem : NSObject
-(void) insertFileSystem: (id<FileManagerProtocol>) file;
@end
實作:
#import "FileManagerSystem.h"
@implementation FileManagerSystem
-(void)insertFileSystem:(id<FileManagerProtocol>)file
{
[file read];
[file writer];
}
@end
3.定義新的檔案類來遵守我們的檔案讀寫協定,之後就可以放入到我們的管理系統中進行管理
檔案類1
#import <Foundation/Foundation.h>
#import "FileManagerProtocol.h"
@interface File : NSObject<FileManagerProtocol>
@property (nonatomic,strong) NSString *fileName;
@end
#import "File.h"
@implementation File
//實作協定中的方法
-(void)read
{
NSLog(@"我是檔案%@,你可以對我進行閱讀",_fileName);
}
-(void)writer
{
NSLog(@"我是檔案%@,你可以對我進行修改",_fileName);
}
@end
在定義一個履歷檔案,同樣遵守我們的檔案協定
#import <Foundation/Foundation.h>
#import "FileManagerProtocol.h"
@interface JianLi : NSObject<FileManagerProtocol>
@property (nonatomic, strong) NSString *fileName;
@end
#import "JianLi.h"
@implementation JianLi
-(void)read
{
NSLog(@"對履歷%@的讀", _fileName);
}
-(void)writer
{
NSLog(@"對履歷%@的寫", _fileName);
}
@end
然後我們可以把各種不同檔案但都遵循我們檔案協定的檔案放入到我們的檔案管理系統進行管理
1 //聲明檔案,然後放入檔案管理系統
2 File *file = [File new];
3 file.fileName = @"浪潮之巅";
4
5 //執行個體化檔案二,隻要符合檔案協定即可
6 File *file1 = [File new];
7 file1.fileName = @"file1";
8
9 JianLi *jianLi = [JianLi new];
10 jianLi.fileName = @"lusashi的履歷";
11
12 //執行個體化檔案管理系統
13 FileManagerSystem *fileSystem = [FileManagerSystem new];
14
15
16
17 //把書加入到管理系統中
18 [fileSystem insertFileSystem:file];
19 [fileSystem insertFileSystem:file1];
20 [fileSystem insertFileSystem:jianLi];
運作結果:
1 2014-08-14 12:05:47.956 Memory[985:303] 我是檔案浪潮之巅,你可以對我進行閱讀
2 2014-08-14 12:05:47.958 Memory[985:303] 我是檔案浪潮之巅,你可以對我進行修改
3 2014-08-14 12:05:47.958 Memory[985:303] 我是檔案file1,你可以對我進行閱讀
4 2014-08-14 12:05:47.959 Memory[985:303] 我是檔案file1,你可以對我進行修改
5 2014-08-14 12:05:47.959 Memory[985:303] 對履歷lusashi的履歷的讀
6 2014-08-14 12:05:47.959 Memory[985:303] 對履歷lusashi的履歷的寫
作者:青玉伏案
出處:http://www.cnblogs.com/ludashi/
本文版權歸作者和共部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。
如果文中有什麼錯誤,歡迎指出。以免更多的人被誤導。
收履歷:某網際網路公司,招聘iOS/Android靠譜工程師,入職後,可内部聯系樓主,有小禮品贈送,有意者可郵箱投遞履歷:[email protected]