在.NET中有介面的概念,介面主要用於定義規範,定義一個介面關鍵字使用interface。而在Object C 中@interface是用於定義一個類的,這個和.NET中有點差別。在Object C中有一個協議(protocol) 的概念,這個和.NET中的interface類似。
協議(Protocol) 在列出的方法在本類中並沒有相應實現,而是別的類來實現這些方法,而定義協議必須使用protocol關鍵字。
一. 如何定義protocol的定義
如何使用XCode新建一個協議.h 檔案
定義協議程式碼如下:
#import <Foundation/Foundation.h> @protocol ProtocolCom <NSObject> @required -(void) eat; @optional -(void) write; @end
從以上程式碼可以看到,我們可以瞭解到定義一個協議基本如下結構:
@protocol protocolName<NSObject>
@required
//方法宣告
@optional
//方法宣告
.......
@end
從剛才的程式碼中,定義了一個名為ProtocolCom的協議,其中有兩個方法 eat ,write; 上面也提到過了,protocol相當於.net中的interface 介面,介面就是用於定義規則的,但是Object C中的協議和.NET中的interface還是有點區別的,這裡就涉及到@required,@optional 。 這兩個標註在方法上面是有特殊含義的,這個後面詳細說明。
#import <Foundation/Foundation.h> @protocol ProtocolCom @required -(void) eat; @optional -(void) write; @end
從上面修改的程式碼對比來看,在協議定義後面缺少了<NSObject> ,這段程式碼仍然能夠正常執行,其實<NSObject>也本身可以理解為ProtocolCom要遵循NSObject 協議,這個和.NET中一個類如果沒有顯示指定繼承哪個類,那麼預設就是繼承的Object類的道理是一樣的,所以這裡可以省略。
這裡我在定義一個協議MyProtocol,這個協議必須遵循協議ProtocolCom協議。剛才上面已經瞭解到了協議後面跟<NSObject>,道理一樣如果MyProtocol要遵循協議ProtocolCom就是用此種方式來實現,具體程式碼如下:
#import <Foundation/Foundation.h> #import "ProtocolCom.h" @protocol MyProtocol <ProtocolCom> @required -(void) setname; @optional -(void) setage; @end
在Object C 協議中並不習慣說繼承,而是是用遵從或者遵循,比如A協議遵循B協議。這裡專業上得術語可能不太準確,姑且這麼說,先理解意思。
然後我們是用一個新的類來實現協議MyProtocol中的所有方法。
#import <Foundation/Foundation.h> #import "MyProtocol.h" @interface Student : NSObject<MyProtocol> @end ------------------------------------------- #import "Student.h" @implementation Student -(void) write{ NSLog(@"write"); } -(void) eat{ NSLog(@"eat"); } -(void) setage{ NSLog(@"Student---setage"); } -(void) setname{ NSLog(@"Student----setname"); } @end
從以上程式碼可以看出類Student實現了協議MyProtocol,因為協議MyProtocol遵循協議ProtocolCom,所以協議MyProtocol有四個方法。所以在Student類中可以實現四個方法。
二. 協議相關約束
@required 用於表示協議中該方法必須在類中實現,預設[如果不加則預設為@required]
@optional 用於表示協議中該方法在類中可以選擇實現
看到這裡貌似比.NET中的要高階點,.NET中interface定義的所有方法在子類中都必須實現。如果用@required標識的方法在子類中沒有實現那麼編譯編譯會報錯,提示該方法必須實現。而@optional則不會。下面這段程式碼就會存在問題:
#import "Student.h" @implementation Student -(void) write{ NSLog(@"write"); } -(void) eat{ NSLog(@"eat"); } -(void) setage{ NSLog(@"Student---setage"); } @end
三. 同時遵循多個協議
在.NET中一個類也可以實現多個介面,在Object C中同樣如此,一個類可以實現遵循多個介面,基本語法如下:
@interface className:parentName<ProtocolName1,ProtocolName2,...>
......
@end
雖然上面簡單了點,但是還是能夠看明白表達的意思,下面看一段程式碼說明:
這裡從新定義一個新的協議NewProtocol,裡面有一個必須實現的方法getname
#import <Foundation/Foundation.h> @protocol NewProtocol <NSObject> @required -(NSString*) getname; @end
然後從新定義一個新的類Children,這個類必須遵循協議NewProtocol和協議MyProtocol ,具體程式碼如下:
#import <Foundation/Foundation.h> #import "MyProtocol.h" #import "NewProtocol.h" @interface Children : NSObject<MyProtocol,NewProtocol> @end
在Children.m程式碼中要實現兩個協議中必須實現的方法
#import "Children.h" @implementation Children -(void) eat{ NSLog(@"eat"); } -(void) setname{ NSLog(@"Student--setname"); } -(NSString*) getname{ return @"qingyuan"; } @end
下面使用測試程式碼,看看一個類遵循兩個協議的效果:
Children *child=[[Children alloc] init]; NSString *name=[child getname]; NSLog(@"name=%@",name); [child eat]; [child setname];
在上面的程式碼中可以正常執行,但是要注意如果可選擇實現的方法沒有去實現,而在這裡去呼叫的話會報錯。
四. 正式協議和非正式協議
說道正式協議和非正式協議,其實只要理解兩個關鍵字@interface 和 @protocol 。先看看下面一個列子
#import <Foundation/Foundation.h> #import "MyProtocol.h" #import "NewProtocol.h" @interface Children : NSObject<MyProtocol,NewProtocol> -(void) love; @end
在Children.h中定義了一個新的方法love,之前我們也一直這樣寫的,沒有任何問題。再看下面一段程式碼
#import "Children.h" @implementation Children -(void) eat{ NSLog(@"eat"); } -(void) setname{ NSLog(@"Student--setname"); } -(NSString*) getname{ return @"qingyuan"; } @end
使用編譯器編輯,程式碼並沒有報錯。在Children.m中沒有love方法的實現。 這個和我們之前所見到的程式碼似乎有點不一樣啊,有點不理解,理論上Children.m中應該實現love方法的。
上面看到的這種情況,就好比Protocol中的@optional方法,是可以選擇實現的,其實我們就稱作@interface Children : NSObject 就是一個非正式協議。
剛才也注意到了,那是不是Protocol中的@optional標識的方法也就是非正式協議呢。在這裡網路上有些爭議,個人也沒有完全明白,但是個人理解這個還是不一樣的。@protocol是一種既定的規則,如果要做就必須遵循這種規則,而@interface有點象描述,用於描述類是幹什麼的. 而兩者因為都可選擇實現其他的方法,所以感覺有點類似。
五. 協議總結
Object C中有點特殊的時協議不引用任何類,任何類都可以實現已經定於好的協議。
bool flag1=[child conformsToProtocol:@protocol(NewProtocol)]; NSLog(@"%d",flag1); bool flag2=[child conformsToProtocol:@protocol(MyProtocol)]; NSLog(@"%d",flag2); bool flag3=[child conformsToProtocol:@protocol(ProtocolCom)]; NSLog(@"%d",flag3);
從以上程式碼可以看得出,conformsToProtocol 方法用於判斷某個類是否遵循某個協議,返回值為bool型別,即使協議是通過"繼承"過來的也可以。
本文到此結束,學習筆記可能有諸多問題,望請牛人勿噴,菜鳥的學習需要鼓勵!