objective-C中的介面與泛型

來源:互聯網
上載者:User
先承認我是標題黨,因為在obj-c的世界中,官方根本沒有"介面"與"泛型"這樣的說法。不過在obj-c中有二個與之接近的概念"非正式協議(interface)"與"正式協議(protocal)"。非正式協議在obj-c中的關鍵字雖然也是interface,但是這個跟c#中的介面(interface)並不完全相同。回憶一下前面學過的內容,我們定義一個類Sample時,總是會先產生一個Sample.h,代碼如下:
#import <Foundation/Foundation.h>@interface Sample : NSObject {}-(void) HelloWorld;@end
它表明Sample類中,約定了"應該"有一個名為HelloWorld的方法(註:我這裡說的是應該,而不是必須),它只是一種君子協定。

如果我們在Sample.m中,並不遵守這個約定(即:不實現這個方法),編譯時間xcode會給出警告,如。但最後還是會編譯成功(即:編譯器對此是睜一隻眼閉一隻眼,預設了Sample類的這種不忠行為)

中的提示:Incomplete implementation of class "Sample". 意為:Sample類並未完全實現interface中約定的方法。這就是obj-c中的協議跟c#中的介面不一樣的地方:在c#中介面是強制必須實現的,否則編譯這一關就過不了,而obj-c雖然在編譯時間會警告,但是最終能編譯通過。正式協議(protocal)其實就是非正式協議(interface)換了一種寫法而已,看上去更正規一些,語義上更強烈一些:要求採用該協議的類,"必須"實現協議中約定的方法。但是比較娛樂的是,即使是號稱正式協議,編譯器在編譯時間,遇到不守規矩的情況,仍然只是給出警告。(當然正式協議也有它存在的意義,後面會提到)這裡我們定義一個IQuery的協議IQuery.h

@protocol IQuery-(void) Query:(NSString*) sql;@end
除了把關鍵字@interface換成了@protocal,其它的基本上沒變化。下面定義一個類DBQuery,並採用這個正式協議DBQuery.h
#import <Foundation/Foundation.h>#import "IQuery.h"@interface DBQuery : NSObject<IQuery> {}@end
注意這裡的DBQuery:NSObject<IQuery>,它表明DBQuery繼承自NSObject,同時要實現介面IQuery。DBQuery.m
#import "DBQuery.h"@implementation DBQuery-(void) Query:(NSString *)sql{NSLog(@"Query is called. sql:%@",sql);}@end
當然,如果在DBQuery.m中不實現方法Query,也能編譯通過,只是會收到一個警告。也許到目前為止,你會覺得protocal跟interface比起來,都是類似的概念,protocal設計純屬多餘。其實不然,protocal存在的一個重要意義在於:正式協議(protocal)可以將業務中的方法定義剝離出來,形成一個單獨的檔案,這跟傳統OO中的提取介面是不謀而合的。如果遇到二個系統需要交換資料,可以制定一套雙方都遵守的protocal,然後這二個系統中都把這個協議檔案添加到項目中,實現它即可。這一功能,非正式協議(@interface)就做不到。(不信大家可以把NSObject<IQuery>中的IQuery改成其它類的interface定義名稱試試,編譯根本通不過)此外,obj-C 2.0中對正式協議還做了一些擴充,允許把正式協議中的方法標識為“必須實現(@requied)”和“可選實現(@optional)”二類,如果協議中的方法被標識為@optional,即使採用該協議的類不實現這些方法,編譯器也不會給出警告。這賦予了正式協議更多的靈活性。樣本如下:
@protocol IQuery@required-(void) Query:(NSString*) sql;@optional-(void) HelloWorld; @end

有了@optional關鍵字以後,其實“非正式協議”在語義上完全可以被“正式協議”所取代,事實上Cocoa中的非正式協議都在逐漸被標有@optional方法的正式協議所代替。

如果你在XCode的代碼中,選中NSObject,右擊-->Jump to Definition,會發現NSObject其實就是一個interface或protocal

選擇protocal NSObject 繼續,會看到NSObject.h檔案中關於protocal NSObject的定義

同樣的,你還可以看到interface NSObject的定義

從這裡可以看到,非正式協議的interface NSObject其實最終採用的還是正式協議protocal NSObject.

也就是說,在obj-c的OO世界中,身為萬物之祖的NSObject其實也就一個"正式協議”,所以從NSObject派生出的所有類,都只是在遵守一個或多個協議而已。

另一個話題泛型

在obj-c中,一切皆為指標。前面的學習中,我們已經接觸到了一種特殊的類型id,它可以認為是一種特殊的指標:可以指向任何類型的對象。id 再加上正式協議,能夠達到形似c#中泛型的效果(註:只是形似,並非神似)

#import <Foundation/Foundation.h>#import "IQuery.h"@interface DBQuery : NSObject<IQuery> {}-(void) test:(id<IQuery>) obj;@end

注意這裡的 -(void) test:(id<IQuery>) obj; 這表明test方法接受一個任意類型的對象做為參數,但是該參數對象必須實現介面IQuery(也可以說成該參數對象必須採用正式協議IQuery),是不是跟c#中的

void test(List<IQuery> obj) 長得很象? 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.