類目,延展,和協(xié)議,代理

為什么使用類目
是一種為現(xiàn)有的類添加新方法的方式
有時(shí)需要對(duì)現(xiàn)有的類添加一些方法,之前都是通過繼承相關(guān)的類,然后再子類中擴(kuò)展我們需要的相應(yīng)的方法.
Objective-C是一種動(dòng)態(tài)語言,可以給現(xiàn)有的類添加新的方法,這便是對(duì)類目的延展.

類目(category):為已知的類添加新的方法,無論是否知道類的源代碼,這些類包括自己定義的類和系統(tǒng)已有的類。
類目的作用主要有三個(gè)方面:
1、將類的實(shí)現(xiàn)分散到多個(gè)不同的文件中,將多個(gè)類目的聲明放入同一個(gè).h文件中,將實(shí)現(xiàn)放入多個(gè).m方法中。
2、使用類目創(chuàng)建對(duì)私有方法的前向引用,就是為類創(chuàng)建私有方法。
3、向?qū)ο筇砑臃钦絽f(xié)議,現(xiàn)在逐漸被正式協(xié)議做替代。

Paste_Image.png
Paste_Image.png
Paste_Image.png

類目的實(shí)現(xiàn)
類目聲明之后需要對(duì)類擴(kuò)展出來的方法進(jìn)行實(shí)現(xiàn)

Paste_Image.png

使用擴(kuò)展后的方法

#import <Foundation/Foundation.h>
#import "NSString+MyNumber.h"http://添加類目頭文件
int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        //創(chuàng)建四個(gè)字符串
        NSString *str1=@"gdsfgsdfgfdgdfs";
        NSString *str2=@"fgsagsdfgfdsg";
        NSString *str3=@"打開分為飛大廈俄方飛";
        NSString *str4=@"jfghjfghjfghj";
        
        //求出每一個(gè)字符串的長(zhǎng)度
//        int l1=(int)[str1 length];
//        int l2=(int)[str2 length];
//        int l3=(int)[str3 length];
//        int l4=(int)[str4 length];
//        
//        //轉(zhuǎn)為對(duì)象
//        NSNumber *m1=[NSNumber numberWithInt:l1];
//        NSNumber *m2=[NSNumber numberWithInt:l2];
//        NSNumber *m3=[NSNumber numberWithInt:l3];
//        NSNumber *m4=[NSNumber numberWithInt:l4];
        
        //創(chuàng)建一個(gè)可變的字典
        NSMutableDictionary *mDic=[NSMutableDictionary new];
        
        //添加對(duì)象到字典中
//        [mDic setObject:m1 forKey:str1];
//        [mDic setObject:m2 forKey:str2];
//        [mDic setObject:m3 forKey:str3];
//        [mDic setObject:m4 forKey:str4];
        
        //使用類目后修改為
        [mDic setObject:[str1 getStrLength] forKey:str1];
        [mDic setObject:[str2 getStrLength] forKey:str2];
        [mDic setObject:[str3 getStrLength] forKey:str3];
        [mDic setObject:[str4 getStrLength] forKey:str4];
        
        //輸出
        NSLog(@"%@",mDic);
    }
    return 0;
}

注意類目里面只能寫方法,不能寫聲明和屬性,所以,類目不能作為接口來用

類目的局限性
-類目無法向已有類中添加實(shí)例變量
-如果類目中的方法和已有類中的方法名稱沖突時(shí),類目中的方法優(yōu)先級(jí)高,如果方法名沖突,已有類中的原始方法便無法使用
-在使用類目的時(shí)候,最好是將自己擴(kuò)展的方法和原始方法區(qū)分開來

類目的作用
有三個(gè)方面:
1.將類的實(shí)現(xiàn)分散到多個(gè)不同的文件中
-將多個(gè)類目的聲明放入同一個(gè).h文件中
-將實(shí)現(xiàn)放入多個(gè).m方法中
2.使用類目創(chuàng)建對(duì)私有方法的前向引用
-就是為類創(chuàng)建私有方法
3.向?qū)ο筇砑臃钦絽f(xié)議
-現(xiàn)在逐漸被正式協(xié)議做替代

利用類目分散實(shí)現(xiàn)類
-類的@implementation部分只能寫在一個(gè).m文件中
-對(duì)于大型的類,可以使用類目將類的實(shí)現(xiàn)間接的放入多個(gè).m文件中
-將多個(gè)類目的聲明放入同一個(gè).h文件中,包括多個(gè)類目聲明的@interface和@end

類私有的方法
-Objective-C中沒有絕對(duì)意義上的私有方法
-在.h文件中聲明的方法都屬于公開的方法,意味著開放給別人調(diào)用
-如果不想公開某些方法,可以不在.h文件中聲明
-這樣的方法可以被本類中的其他方法所調(diào)用
-如果在類外面強(qiáng)行調(diào)用這些未公開的方法,也能調(diào)用,但是會(huì)有編譯器警告

類的延展
延展(extension):
在自己類的實(shí)現(xiàn)文件中添加類目(匿名類目)來聲明私有方法.(只有本類的.m文件中才能使用)

類的延展可以讓類方法成為類的私有方法
將私有方法聲明到一個(gè)匿名類目中,并且將這個(gè)匿名類目放到類的.m文件里
然后在類的.m的@implementation部分將這個(gè)匿名類目中的私有方法進(jìn)行實(shí)現(xiàn)
這樣的也能夠?qū)懗鏊接蟹椒ǎ峭瑯右部梢詮?qiáng)行在類外部調(diào)用,也會(huì)有編譯器警告

使用類目對(duì)私有方法反向引用

-如果私有方法的聲明放入一個(gè)匿名類目中,并且這個(gè)類目放入一個(gè).h文件中那么這個(gè).h文件可以看做私有的API
-私有API可以不公開,只開放給許可者來調(diào)用
然后在使用私有API時(shí)將那個(gè).h文件導(dǎo)入,然后調(diào)用私有方法,編譯器警告便會(huì)消失

respondsToSelector
用來檢查某一個(gè)對(duì)象能否調(diào)用某一個(gè)方法(檢查方法時(shí)候有實(shí)現(xiàn))
創(chuàng)建了NSObject的類目之后,類目中聲明方法對(duì)于NSObject的子類來說如何檢查是否實(shí)現(xiàn)了哪個(gè)方法
因?yàn)榭赡芤{(diào)用某個(gè)NSObject類目中聲明的方法,在調(diào)用時(shí)需要判斷是否能夠響應(yīng)才行,否則會(huì)造成程序崩潰

MyClass *mc= [MyClass new];
if([mc respondsToSelector:@selector(test)])
{
            [mc test];
}
else
{
        NSLog(@"未實(shí)現(xiàn)test方法!");
}

Objective-C中的協(xié)議
協(xié)議是一個(gè)方法列表,采用協(xié)議時(shí)需要在聲明類時(shí)說明要采用的協(xié)議

協(xié)議的聲明
協(xié)議就是一種標(biāo)準(zhǔn),用來定義了實(shí)現(xiàn)什么,不關(guān)心具體怎么實(shí)現(xiàn)
OC的協(xié)議是由@protocol聲明的一組方法列表
要求其它的類去實(shí)現(xiàn),相當(dāng)于@interface部分的聲明

@required標(biāo)注的方法為必須實(shí)現(xiàn)方法(默認(rèn)不寫為必須實(shí)現(xiàn))
@optional標(biāo)注的方法為可以選擇實(shí)現(xiàn)

@protocol 協(xié)議名稱
//方法列表
 @end

協(xié)議的實(shí)現(xiàn)
方式:
接口文件 一個(gè)類可以通過協(xié)議,用來遵循多個(gè)類中的方法,這樣可以做到多繼承的效果

@interface ClassName : 父類名 <協(xié)議1,協(xié)議2…>
@end

實(shí)現(xiàn)文件

@implementation ClassName
    //實(shí)現(xiàn)協(xié)議中的方法
@end

具體實(shí)現(xiàn)方法

@protocol MyProtocol <NSObject>
@required//必須實(shí)現(xiàn)
-(int) addX:(int) x andY:(int) y;
@optional//可選實(shí)現(xiàn)
-(int) substructX:(int) x andY:(int) y;
@end

協(xié)議和數(shù)據(jù)類型
聲明實(shí)例變量或方法可以指定協(xié)議名稱
id類型可以指向任何類型的

@interface MyClass
{
    id<MyProtocol> myVar; 
}
@end

要求傳入的參數(shù)必須采用MyProtocol協(xié)議

 -(void) methodName:(id<MyProtocol>) obj
{
    //方法代碼
}

檢查對(duì)象是否實(shí)現(xiàn)了某個(gè)協(xié)議
可以通過對(duì)象的下列方法來判斷是否遵循某協(xié)議(confrorms:遵守)

conformsToProtocol:@protocol (協(xié)議名)

在此創(chuàng)建一個(gè)代理使用的實(shí)例
先創(chuàng)建兩個(gè)類,繼承NSObjective
一個(gè)被代理的類,命名為HouseMan
一個(gè)代理的類,命名Medium

HouseMan.h接口文件中實(shí)現(xiàn)

//  房東
#import <Foundation/Foundation.h>

//1.聲明協(xié)議
@protocol GetHoseProtocol <NSObject>

-(void)getRent;//房租的方法
@end
@interface HouseMan : NSObject

//2.創(chuàng)建一個(gè)代理人的屬性 在此簽訂一個(gè)協(xié)議
@property(nonatomic,assign)id<GetHoseProtocol> delegate;

//3.協(xié)議的方法
-(void)houseRent;

@end

HouseMan.m實(shí)現(xiàn)文件中實(shí)現(xiàn)

//4.實(shí)現(xiàn)需要代理的方法
-(void)houseRent
{
    [self.delegate getRent];//呼叫被代理人去做
}

Medium.h接口文件中實(shí)現(xiàn)


#import <Foundation/Foundation.h>

#import "HouseMan.h"http://5.包含代理人的頭文件

@interface Medium : NSObject<GetHoseProtocol>//6.被代理人和代理人簽訂協(xié)議

//7聲明代理人的屬性
@property (nonatomic, strong) NSString *name;

Medium.m實(shí)現(xiàn)文件中

#import "Medium.h"

@implementation Medium

//7.實(shí)現(xiàn)被代理人的方法
-(void)getRent
{
    NSLog(@"正在收房租");
}

@end

最后在main.m文件中

#import <Foundation/Foundation.h>

//包含頭文件
#import "HouseMan.h"
#import "Medium.h"

int main(int argc, const char * argv[]) 
{
    @autoreleasepool
    {
        //創(chuàng)建代理對(duì)象
        Medium *m=[Medium new];
        m.name=@"房屋中介";
        
        //創(chuàng)建被代理對(duì)象
        HouseMan *h=[HouseMan new];
        
        //給代理對(duì)象賦值
        h.delegate=m;
        
        //被代理人呼叫代理人實(shí)現(xiàn)方法 這個(gè)方法是在被代理人種實(shí)現(xiàn)的
        [h houseRent];   
    }
    return 0;
}

設(shè)計(jì)模式

設(shè)計(jì)模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。

-設(shè)計(jì)模式是某個(gè)具體編程問題的通用化,可以復(fù)用的解決方案
-沒有一種可以從前一個(gè)方案中完全復(fù)用代碼的情況,但是可以使用前一次的解決問題時(shí)使用的思想
-設(shè)計(jì)模式可以在遇到編程問題時(shí)會(huì)想起一個(gè)正確的解決方案
-常見的設(shè)計(jì)模式有:?jiǎn)卫J?、委?代理)模式、觀察者模式、職責(zé)鏈模式等等

委托模式
在委托模式中,程序中的一個(gè)對(duì)象代表另外一個(gè)對(duì)象執(zhí)行某個(gè)動(dòng)作,或者與之相互協(xié)作共同完成某個(gè)任務(wù)。
Cocoa Touch廣泛使用委托(delegate),它是負(fù)責(zé)為其他對(duì)象處理特定任務(wù)的類。通過委托,我們能夠在某些預(yù)定義時(shí)間內(nèi)為發(fā)布委托的類做一些工作。

所謂代理,就是指一方授予他方代理權(quán),他方依代理權(quán)與第三方進(jìn)行法律行為,其行為后果由一方承擔(dān)的一種民事法律制度。委托是一方將一定的事務(wù)委諸于另一方實(shí)施的法律制度。

委托和代理的區(qū)別:
第一,委托規(guī)范的是委托人和受托人雙方之間的關(guān)系;而代理規(guī)范的是本人、代理人和第三人的關(guān)系。
第二,代理關(guān)系中代理人代理的對(duì)象是進(jìn)行意思表示和接受意思表示的行為;而委托中受托人代為實(shí)施的行為可以是法律行為,也可以是事實(shí)行為。
第三,代理包括對(duì)內(nèi)和對(duì)外兩種關(guān)系,對(duì)內(nèi)是代理人和被代理人之間的關(guān)系,而對(duì)外是代理人和第三人之間的關(guān)系;而委托只是委托人和受托人之間的關(guān)系。

簡(jiǎn)單的總結(jié):
-委托就是有兩個(gè)對(duì)象,一個(gè)變化時(shí),另外一個(gè)能夠知道上面一個(gè)的變化.
-一個(gè)對(duì)象保存另外一個(gè)對(duì)象的引用,被引用的對(duì)象實(shí)現(xiàn)事先確定的協(xié)議,這個(gè)協(xié)議用來把對(duì)象中的變化通知給被引用的對(duì)象
-委托不一定使用到協(xié)議,使用類目一樣能完成,或者協(xié)議類目都不知用,同樣能做到.

delegate屬性都是assign而不是retain為了避免循環(huán)引用造成的內(nèi)存泄露。
循環(huán)引用的問題這樣理解:
-比如在main函數(shù)中創(chuàng)建了兩個(gè)類的對(duì)象A和B,現(xiàn)在引用計(jì)數(shù)都是1?,F(xiàn)在讓A和B互相引用(A有一個(gè)屬性是B對(duì)象,屬性說明是retain;B有一個(gè)屬性是A對(duì)象,屬性說明是retain),現(xiàn)在兩個(gè)對(duì)象的引用計(jì)數(shù)都增加了1,都變成了2。
-現(xiàn)在執(zhí)行 [A release]; [B release]; 此時(shí)創(chuàng)建對(duì)象的main函數(shù)已經(jīng)釋放了自己對(duì)對(duì)象的所有權(quán),但是此時(shí)A和B的引用計(jì)數(shù)都還是1,因?yàn)樗麄兓ハ嘁昧恕?br> -這時(shí)你發(fā)現(xiàn)A和B將無法釋放,因?yàn)橐脶尫臕必須先釋放B,在B的dealloc方法中再釋放A。同理,要想釋放B必須先釋放A,在A的dealloc方法中再釋放B。所以這兩個(gè)對(duì)象將一直存在在內(nèi)存中而不釋放。這就是所謂的循環(huán)引用的問題。
-要想解決這個(gè)問題,一般的方法可以將引用的屬性設(shè)置為assign,而不是retain來處理。

使用非正式協(xié)議的委托模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.項(xiàng)目經(jīng)驗(yàn) 2.基礎(chǔ)問題 3.指南認(rèn)識(shí) 4.解決思路 ios開發(fā)三大塊: 1.Oc基礎(chǔ) 2.CocoaTouch...
    扶光啟玄閱讀 5,202評(píng)論 0 13
  • 1.OC里用到集合類是什么? 基本類型為:NSArray,NSSet以及NSDictionary 可變類型為:NS...
    輕皺眉頭淺憂思閱讀 1,471評(píng)論 0 3
  • 1、Objective-C的類可以多重繼承么?可以采用多個(gè)協(xié)議么?答:不可以多重繼承,可以采用多個(gè)協(xié)議。2、#im...
    亦晴工作室閱讀 684評(píng)論 0 0
  • 你偷走了今日的太陽 已經(jīng)八點(diǎn)還是黑暗一片 我摸黑起來穿好衣服洗漱 等著你過來 你不來 我又回到床上繼續(xù)睡覺 你偷走...
    初五閱讀 10,233評(píng)論 3 13
  • 心情很差。工作生活和情感。 站在別人的角度和站在自己的角度,有時(shí)候人就是那么自私,我還沒有說什么,你就斷定我會(huì)跟你...
    荇菜閱讀 269評(píng)論 0 1

友情鏈接更多精彩內(nèi)容