一、類别(Category)簡介
OC中類别功能強大,它能夠在不使用繼承的情況下向現有的類添加新的方法。特别是在沒有類的源代碼的情況下,通過使用類别依然能夠向該類添加新的方法。
類别的主要有兩個作用,一是向類添加新的方法以拓展類的功能,二時将類的實作部分分布發哦多個檔案中。
二、聲明類别并實作類别方法
1. 類别的聲明與實作的格式如下
#import "目标類名.h"
@interface 目标類名 (類别名稱)
// 方法聲明區
@end
@implementation 目标類名 (類别名稱)
// 方法實作區
@end
其實類别的聲明與實作格式與類的聲明和實作格式類似。差別就是類别聲明後面會加上小括号,而類接口聲明沒有小括号。方法聲明區中給出了類别中的方法聲明,這些方法會附加到目标類中。注意:在附加之後這些方法與類的其它方法沒有任何差別,他們也能夠通路類的成員變量,或是繼承到目标類的子類中。但是,如果目标類和類别都定義了一個簽名完全一樣的方法,則類别中的方法會替換類中定義的方法。如果有兩個類别都定義了一個簽名完全一樣的方法,則調用哪一個方法是不用确定的。另外類中隻能定義方法,不能定義成員變量。
2. 拓展類的功能:
有時候根據需要,比如說一個項目有不同的子產品,要配置設定給不同的人做。這時候就可以使用類别,我們可以定義多個附加到目标類的類别,并在該類别中實作需要實作的方法。
建立檔案---oc file---類名、file type、附加的類名稱
#import "Student.h" //導入這個檔案是位了要知道目标類中有哪些方法
//#import <Foundation/Foundation.h> //不需要導入這個檔案了
// ()代表着一個分類
// ()中的Test代表着分類的名稱
// 不使用@class是因為“分類”是給原類拓展一些方法
@interface Student (Test)
- (void)test2;
@end
#import "Student+Test.h"
@implementation Student (Test)
- (void)test2 {
NSLog(@"這個代表調用的test2");
}
@end
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LcZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jMzcTMzQTM0EjMxgDM1EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
3. 拆分類的實作:
除了拓展類的行為之外,類别還有一個作用就是将類的實作分成若幹部分。
三、協定(代理)--- 隻有聲明.h沒有實作.m,需要其他的類去實作
oc中的協定與java、c#中的借口以及c++中的抽象類相類似,用于定義公共接口,并承諾類需要實作協定中規定的方法。使用協定中最大的好處就是它能夠有效拓展程式的功能。比如說:,通用串行總線(Universal Serial Bus, USB)就是一個協定,它能夠讓計算機周邊裝置連接配接标準化。現在的計算機都配備了USB接口,這樣能夠有效拓展計算機的功能。USB協定定義了接口的尺寸、電壓、電流大小等規範,隻要裝置符合USB協定就可以介入到計算機中使用。至于裝置的具體作用可以由廠家自己進行設計規劃。
java、c#接口、c++抽象類要求實作它的非抽象類必須實作它規定的方法。objective-c中的協定更加靈活,他可以規定哪些方法必須實作,那些方法可以有選擇性的地實作。
1. 簡介:
1. Protocol:就是一個用途,用來聲明一大堆方法(不能聲明成員變量),不能寫實作;
2. 隻要某個類遵循了這個協定,就擁有了這個協定中的所用方法;
3. 隻要父類遵守某個協定,那麼子類也遵循;
4. Protocol聲明的方法可以讓任何類去實作,protocol就是協定;
5. OC不能繼承多個類(單繼承)(:),但是能夠遵守多個協定。(<>)
6. 基協定:<NSObject>是基協定,是最根本的協定,其中聲明了很多基本的方法;
7. 協定可以遵守協定,一個協定遵守了另一個協定,就可以擁有另一份協定中的方法聲明;
2. 聲明協定
關鍵字Protocal,和類的外部接口聲明類似,協定定義在@protocol與@end指令之間。@protocol後接協定名稱。并使用@required與@optional規定哪些方法必須由采用該協定的類實作,哪些方法可以有選擇性地實作,預設為@required(必須要實作)。
格式:
@protocol 協定名 <父協定>
定義方法
@end
注:定義協定的關鍵字是@protocol,同時協定也是可以繼承父協定的。
建立一個協定:
#import <Foundation/Foundation.h>
// MyProtocol就是協定,這個協定遵守基協定<NSObject>
@protocol MyProtocol <NSObject>
// 在協定中可以聲明很多有用的方法
// @property int age; 在協定中不能聲明成員變量,隻能是聲明方法,也不能實作方法
@required
// @required關鍵字主要用于程式員之間的交流,要求實作
- (void)pint;
- (void)haha;
@end
@interface MyProtocol : NSObject
@end
遵守協定:
#import <Foundation/Foundation.h>
#import "MyProtocol.h"
// 在類的聲明中加入協定的頭檔案
// Person類的聲明,這個類繼承了NSObject類,遵守MyProtocol協定
@interface Person : NSObject <MyProtocol>
@end
或者按照下面的實作:
#import <Foundation/Foundation.h>
// #import "MyProtocol.h"
// 在類的聲明中加入協定的頭檔案
// 方式二使用一種方式,與前面将的@class前向聲明功能一樣;在.m檔案中在進行導入也是可以
@protocol MyProtocol;
// Person類的聲明,這個類繼承了NSObject類,遵守MyProtocol協定
@interface Person : NSObject <MyProtocol>
@end
完成協定中聲明的方法的實作:
#import "Person.h"
@implementation Person
// 在這裡進行遵守的協定裡所聲明的方法的實作
- (void)pint {
NSLog(@"nihao!");
}
- (void)haha {
NSLog(@"nibuhao!");
}
@end
測試程式:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "MyProtocol.h"
int main(int argc, const char *argv[])
{
@autoreleasepool {
Person *per = [[[Person alloc] init] autorelease];
[per pint];
[per haha];
}
}
3. 注意點
1.協定的定義
@protocol 協定名稱 <NSObject>
//方法聲明清單
@end;
2.如何遵守協定
(1)類遵守協定
@protocol 類名 :父類名 <協定名稱1,協定名稱2>
@end
(2)協定遵守協定
@protocol 協定名稱 <其他協定名稱>
@end;
3.協定方法聲明中的關鍵字
(1)required (預設)要求實作,若沒有實作則警告但不報錯
(2)Optional 不要求實作
4.定義變量時遵守協定的限制(隻能是對象)
類名<協定名稱> *變量名 NSObject<.Myprotocol> *obj;
Id <協定名稱> 變量名 id <.Myprotocol> obj1;
5.Property中聲明的屬性也可以做遵守協定的限制
@property (nonatomic ,strong ) 類名<協定名稱> *屬性名;
@property (nonatomic ,strong ) id<協定名稱> 屬性名;
6.補充:協定本身寫在頭檔案中,但也可以定義在任何地方。當這個協定隻有這個類使用遵守時,一般把協定寫在這個類裡面(同一檔案),當這個協定需要多個類去實作時,就寫在外邊單獨的檔案中(建立)。
4. 實作協定
協定定義後,需要其他類遵循(實作)協定。在類的外部接口中,可以定義其他類遵從哪些協定。類不允許繼承多個類,但是類允許遵從多個協定。當某個類需要遵從多個協定時,可以在類的接口中的@interface指令後給出,協定名稱必須位于尖括号内,多個協定名稱之間使用逗号分開。
5. 使用協定限制對象類型與行為
協定可以限定對象類型,并在程式的編譯期間給出警告。
6. 在程式中我們跟難知道程式是否實作了協定這一功能。這時候需要我們對協定進行判斷。
// conformToProtocol: 判斷是否遵守了某協定
if ([stu conformsToProtocol:@protocol(Read)]) {
NSLog(@"對象遵守了協定");
}
// 判斷是否遵守了某内容
if (![stu respondsToSelector:@selector(haha)]) {
NSLog(@"對象沒有實作這個方法");
}
7. 限制對象實作協定
// 協定限制
void demo03()
{
// 限制它遵守協定 會報錯 意思是不比對
// NSObject<MyProtocol> *peo = [[NSObject alloc] init];
NSObject<MyProtocol> *peo = [[Person alloc] init];
peo = nil;
// id<MyProtocol> *peo1 = [[Person alloc] init]; id 就是相當于 -- 類 *
id<MyProtocol> peo1 = [[Person alloc] init];
peo1 = nil;
}
**:協定的相關案例後面的博文中會繼續分享。= =