第十二章類別


利用Objective-C的動態運行時分配機制,可以爲現有的類添加新方法,這種爲現有的類添加新方法的方式稱爲類別catagory,他可以爲任何類添加新的方法,包括那些沒有源代碼的類
類別使得無需創建對象類的子類就能完成同樣的工作
一、創建類別
1、聲明類別
聲明類別與聲明類的形式很相似
@interface NSString(NumberConvenience)
-(NSNumber *)lengthAsNumber;
@end//NumberConvenience
這個聲明有兩個特點:
      (1)現有的類位於@interface關鍵字之後,然後是位於括號中的類別名稱。
         他表示:向NSString類中添加一個名稱爲NumberConvenience的類別
         同名類別有唯一性,但是可以添加任意多的不同名類別
      (2)可以執行希望向其添加類別的類以及類別的名稱,還可以列出添加的方法
         不可以添加新的實例變量,類別生命中沒有實例變量部分

2、實現類別
     @implementation NSString(NumberConvenience)
     -(NSNumber *)lengthAsNumber
     {
         unsigned int length = [self length];
         return ([NSNumber numberWithUnsignedInt : length]);
     }//lengthAsNumber
     @end//NumberConvenience
在實現部分也包括類名、類別名和新方法的實現代碼

3、類別的侷限性
有兩方面侷限性:
        (1)無法向類中添加新的實例變量
        (2)當類別方法與原始類方法名稱衝突時,類別方法將完全取代初始方法從而無法再使用初始方法
無法添加實例變量的侷限可以使用字典對象解決
4、類別的作用
類別主要有3個作用:
        (1)將類的實現分散到多個不同文件或多個不同框架中
        (2)創建對私有方法的向前飲用
        (3)向對象添加非正式協議

二、利用類別分散實現
我們可以將類的接口放入頭文件中,從而將類的實現放入.m文件中
但不可以將@implementation分散到多個不同的.m文件中,使用類別可以完成這一工作

利用類別,可以將一個類的方法組織到不同的邏輯分組中,使編程人員更加容易的閱讀頭文件

舉例代碼:
頭文件CatagoryThing.h包含類的聲明和一些類別,導入Foundation框架,然後帶有3個整型變量的聲明
#import <Foundation/Foundation.h>
@interface CategoryThing : NSObject {
   int thing1;
   int thing2;
   int thing3;
}
@end // CategoryThing
類聲明之後是3個類別,每個類別具有一個實例變量的訪問器,將這些實現分散到不同的文件中
@interface CategoryThing (Thing1)
- (void) setThing1: (int) thing1;
- (int) thing1;
@end // CategoryThing (Thing1)

@interface CategoryThing (Thing2)
- (void) setThing2: (int) thing2;
- (int) thing2;
@end // CategoryThing (Thing2)

@interface CategoryThing (Thing3)
- (void) setThing3: (int) thing3;
- (int) thing3;
@end // CategoryThing (Thing3)
類別可以訪問其繼承的類的實例變量,類別的方法具有最高的優先級
類別可以分散到不同文件中,甚至不同框架中

三、使用類別創建前向引用
如果其他類中的方法未實現,在你訪問其他類的私有方法時編譯器報錯
這時使用類別,在類別中聲明這些方法(不必提供方法實現),編譯器就不會再產生警告

四、非正式協議和委託類別
Cocoa中的類經常使用一種名爲委託(delegate)的技術
委託是一種對象,另一個類的對象會要求委託對象執行他的某些操作
(看不懂,在實踐中學習)

   

#import <Foundation/Foundation.h>

#import "ITunesFinder.h"

int main (int argc, const char *argv[])

{

    NSAutoreleasePool *pool;

     pool = [[NSAutoreleasePool alloc] init];

    NSNetServiceBrowser *browser;

     browser = [[NSNetServiceBrowser alloc] init];

         ITunesFinder *finder;

         finder = [[ITunesFinder alloc] init];//因爲finder是alloc方法創建的,必須在不適用這個對象時將其釋放

         [browser setDelegate: finder];//告知browser使用finder作爲委託對象

         [browser searchForServicesOfType: @"_daap._tcp"  //告知browser對象使用TCP協議去搜索DAAP類型服務

                                       inDomain: @"local."];//表示只搜索本地

         NSLog (@"begun browsing");//表示下面的run循環已經開始

         [[NSRunLoop currentRunLoop] run];//run循環是一種Cocoa構造,他不執行任何處理,等待用戶的操作

         [browser release];//run方法將一直保持運行而不返回,所以包含此行之後的代碼不會被運行

         [finder release];

         [pool release];

         return (0);

} // main

創建一個NSObject的類別稱爲“創建一個非正式協議”,因爲可以作爲任何類的委託對象使用

響應選擇器

選擇器只是一個方法名稱,但它以Objective-C運行時使用特殊方式編碼,以快速執行查詢

可以使用@selector()預編譯指定選擇器,其中方法名位於圓括號中

例如之前的Car類的setEngine:方法的選擇器是:@selector(setEngine:)

而Car類的setTire:atIndex;方法的選擇器如下所示:@selector(setTire:atIndex;)


NSObject提供了一個名爲respondsToSelector方法,該方法詢問對象以確定其是否能夠響應某個特定的消息

舉例代碼:

        Car *car = [[Car alloc] init];

        if([car respondsToSelector:@selector(setEngine:)]){

            NSLog(@"hihi");

         }

選擇器的其他應用

選擇器可以被傳遞,可以作爲方法的參數使用,甚至可以作爲實例變量存儲


小結

類別提供了向現有類添加新方法的手段,即使沒有這些類的源代碼

類別可以將對象的實現分散到多個不同的源文件、甚至多個不同的框架中

使用類別可以聲明非正式協議,非正式協議是NSObject的一個類別,他可以列出對象能夠響應的方法

非正式協議用於委託,委託是一種允許輕鬆定製對象行爲的技術

發佈了0 篇原創文章 · 獲贊 6 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章