OC正式协议和非正式协议

简介:

最近看了些关于objective-c的正式协议和非正式协议的内容,发现还是有些混乱,可能是因为还不熟悉OC,对正式协议和非正式协议的使用还不是很熟练,所以想整理一下

非正式协议,是使用类别category来实现,非正式协议是NSObject的一个类别,这样任何类的对象都可以作为委托对象来使用,它可以列出对象能够执行的所有方法,这样用来实现委托, 我们可以使用选择器来判断该非正式协议中是否有这个方法。

正式协议,是一个命名的方法列表,与非正式协议相比不同的是,它要求显示的采用协议,采用协议的方法是在类的@interface声明中列出协议的名称,此时,实现协议的类应该遵守协议,承诺实现协议中的所有方法,否则编译器将会发出警告。

协议类似于C++的纯虚函数,协议只有声明,没有实现,用来在子类中实现,协议中的方法有两类属性,@required和@optional两种,@required属性的要求实现协议的类必须要实现这种方法,而@optional属性的方法则不要求,如果不确定协议是否被实现,可以使用respondsToSelector:@select()来判断。

下面是一个协议的声明和实现实例代码:

声明一个协议myprotocol

  1. @protocol myprotocol <NSObject>  
  2. @optional  
  3. -(void)print:(int)value;  
  4. //可选的方法  
  5.   
  6. @required  
  7. -(int)printValue:(int)value1 andValue:(int)value2;  
  8. //必须实现的  
  9.   
  10. @end  

实现这个协议

mytest.h

  1. #import <Foundation/Foundation.h>  
  2. #import "myprotocol.h"  
  3.   
  4. //实现协议 myprotocol  
  5. @interface mytest : NSObject<myprotocol>   
  6. {  
  7.   
  8. }  
  9. - (void)showInfo;  
  10. @end  
mytest.m

  1. #import "mytest.h"  
  2.   
  3. @implementation mytest  
  4. -(void)showInfo  
  5. {  
  6.     NSLog(@"I am in showInfo");  
  7. }  
  8.   
  9. //实现协议必须实现的  
  10. -(int)printValue:(int)value1 andValue:(int)value2  
  11. {  
  12.     NSLog(@"print value1 %d,value2 %d",value1,value2);  
  13.     return 0;  
  14. }  
  15.   
  16. //实现可选的  
  17. -(void)print:(int)value  
  18. {  
  19.     NSLog(@"print value is %d",value);  
  20. }  
  21.   
  22. @end  
使用这个协议main.m

  1. #import <Foundation/Foundation.h>  
  2. #import "mytest.h"  
  3. #import "myprotocol.h"  
  4.   
  5. int main (int argc, const char * argv[]) {  
  6.     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  
  7.   
  8.     // insert code here...  
  9.     NSLog(@"Hello, World!");  
  10.       
  11.     mytest *test=[[mytest alloc]init];  
  12.     [test showInfo];  
  13.     [test printValue:20 andValue:30];  
  14.     //print协议是可选的,所以在用之前一定要判断是否实现了,不然可能会出错,使用下面的方法  
  15. //  [test print:20];  
  16.     SEL sel=@selector(print:);  
  17.     if([test respondsToSelector:sel]){  
  18.         [test print:11];  
  19.     }  
  20.       
  21.     //用协议的方式实现  
  22.     id<myprotocol> protocol =[[[mytest alloc]init]autorelease];  
  23.     [protocol showInfo];  
  24.     [protocol printValue:200 andValue:300];  
  25.     if([protocol respondsToSelector:@selector(print:)]){  
  26.         [protocol print:111];  
  27.     }  
  28.   
  29.     [test release];  
  30.     [pool drain];  
  31.     return 0;  
  32. }  
下面介绍使用正式协议来实现代理,或者叫委托,委托是一中推向,另一个类的对象会要求委托对象来执行它的某些操作。

下面的例子,有一个dog类,一个person类,每个person对象有一个狗,这条狗仅仅属于这个主人,狗会定时的通知主人,也就是调用person类的一些方法,这样在狗的类中就需要一个person的代理,要求主人调用一些方法,机制类似回调,如下:

dog.h

  1. #import <Foundation/Foundation.h>  
  2. @protocol dogBark;  
  3.   
  4. @interface Dog : NSObject {  
  5.     int _ID;  
  6.     NSTimer *timer;  
  7.     int barkCount;  
  8.     id <dogBark> delegate;        //存放狗的主人  
  9.       
  10. }  
  11. @property int ID;  
  12. @property (assign)id <dogBark> delegate;  
  13.   
  14. @end  
  15.   
  16. //定义一个人和狗通讯的协议 protocol  
  17. @protocol dogBark<NSObject>  
  18. -(void)bark:(Dog*)thisDog count:(int)count;  
  19.   
  20. @end  
dog.m

  1. #import "Dog.h"  
  2.   
  3.   
  4. @implementation Dog  
  5. @synthesize ID=_ID;  
  6. @synthesize delegate;  
  7. -(id)init  
  8. {  
  9.     if(self = [super init]){  
  10.         //创建一个定时器user,每隔1.0s 就调用updateTimer:nil,并传递一个参数nil  
  11.         timer=[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:)  userInfo:nil repeats:YES];  
  12.           
  13.     }  
  14.     return self;  
  15. }  
  16.   
  17. -(void) updateTimer:(id)arg  
  18.   {  
  19.       barkCount++;  
  20.       NSLog(@"dog bar %d",barkCount);  
  21.       //调用主人delegate的bark:count方法,   
  22.       [delegate bark:self count:barkCount]; //回调机制  
  23.   }  
  24.   
  25. @end  

person.h

  1. #import <Foundation/Foundation.h>  
  2. #import "Dog.h"  
  3.   
  4. @interface Person : NSObject<dogBark>  
  5. {  
  6.   
  7.     Dog *_dog;  
  8. }  
  9.   
  10. @property (retain) Dog *dog;  
  11. @end  
person.m

  1. #import "Person.h"  
  2.   
  3. @implementation Person  
  4. @synthesize dog=_dog;  
  5. -(void)setDog:(Dog*)aDog  
  6. {  
  7.     if(_dog!=aDog){  
  8.         [_dog release];  
  9.         _dog=[aDog retain];  
  10.         // 通知dog的主人是当前人,self  
  11.         [_dog setDelegate:self];  
  12.           
  13.     }  
  14. }  
  15.   
  16. //当狗叫的时候,让狗来调用人的方法  
  17. //这个方法来源于dogBark协议,Person类来实现  
  18. -(void)bark:(Dog*)thisDog count:(int)count  
  19. {  
  20.     NSLog(@"Person bark: this dog %d bark %d",[thisDog ID],count);  
  21. }  
  22.   
  23. -(void)dealloc  
  24. {  
  25.     self.dog=nil;  
  26.     [super dealloc];  
  27. }  
  28.   
  29. @end  
主函数mian.m

  1. #import <Foundation/Foundation.h>  
  2. #import "Dog.h"  
  3. #import "Person.h"  
  4.   
  5.   
  6. int main (int argc, const char * argv[]) {  
  7.     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  
  8.   
  9.     // insert code here...  
  10.     NSLog(@"Hello, World!");  
  11.     Person *xiaoli = [[Person alloc]init];  
  12.     Dog *dog=[[Dog alloc]init];  
  13.     [dog setID:10];  
  14.     [xiaoli setDog:dog];  
  15.     [dog release];  
  16.     //程序循环在这里  
  17.     while (1) {  
  18.         [[NSRunLoop currentRunLoop]run];  
  19.     }  
  20.     [xiaoli release];  
  21.       
  22.     [pool drain];  
  23.     return 0;  
  24. }  

使用非正式协议也可以实现委托,前面讲非正式协议是使用类别来实现的,

同样的是一个dog类,一个person类,person类有一条狗,再实现一个NSObject的类别,在类别中实现一个方法,通过dog对象来调用这个方法。

  1. #import <Cocoa/Cocoa.h>  
  2.   
  3. @interface dog : NSObject {  
  4.     int _ID;  
  5.     }  
  6. @property int ID;  
  7.   
  8. @end  
  1. #import "dog.h"  
  2.   
  3. @implementation dog  
  4. @synthesize  ID=_ID;  
  5. -(id)init  
  6. {  
  7.     self=[super init];  
  8.     return self;  
  9. }  
  10.   
  11. @end  
person类

  1. #import <Cocoa/Cocoa.h>  
  2. #import "dog.h"  
  3.   
  4. @interface person : NSObject   
  5. {  
  6.     dog *_mydog;  
  7. }  
  8.   
  9. -(void)setDog:(dog*)aDog;  
  10. -(id)mydog;  
  11. -(void)callFun;  
  12. @end  
  1. #import "person.h"  
  2. #import "nsobject_categroy.h"  
  3.   
  4. @implementation person  
  5.   
  6. -(void)setDog:(dog*)aDog  
  7. {  
  8.     if (_mydog!=aDog) {  
  9.         [_mydog release];  
  10.         _mydog=[aDog retain];  
  11.     }  
  12. }  
  13.   
  14. -(id)mydog{  
  15.     return _mydog;  
  16. }  
  17.   
  18. -(void)callFun{  
  19.     NSLog(@"call Fun!");  
  20.     [_mydog callFromNSObject];  
  21. }  
  22.   
  23. -(void)dealloc{  
  24.     [self setDog:nil];  
  25.     [super dealloc];  
  26. }  
  27. @end  
NSObject类别的实现,也就是非正式协议
  1. #import <Cocoa/Cocoa.h>  
  2.   
  3.   
  4. @interface  NSObject(myCategroy)   
  5. -(void)callFromNSObject;  
  6. @end  
  1. #import "nsobject_categroy.h"  
  2.   
  3.   
  4. @implementation  NSObject(myCategroy)   
  5. -(void)callFromNSObject  
  6. {  
  7.     NSLog(@"I AM NSOBJECT FUNCTIONS");  
  8. }  
  9. @end  
主函数:

  1. #import <Foundation/Foundation.h>  
  2. #import "person.h"  
  3. #import "dog.h"  
  4.   
  5. int main (int argc, const char * argv[]) {  
  6.     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  
  7.   
  8.     // insert code here...  
  9.     NSLog(@"Hello, World!");  
  10.     dog *d=[[dog alloc]init];  
  11.     [d setID:10];  
  12.     person *p=[[person alloc]init];  
  13.     [p setDog:d];  
  14.     [p callFun];  
  15.     [p release];  
  16.     [pool drain];  
  17.     return 0;  
  18. }  
这样就会调用callFromNSObject方法


类别主要有三个功能:

一、利用类别分散实现

二、利用类别创建前向引用,可以实现私有函数

三、非正式协议和委托类别
















本文转自蓬莱仙羽51CTO博客,原文链接:http://blog.51cto.com/dingxiaowei/1366570,如需转载请自行联系原作者

相关文章
|
3月前
|
Swift iOS开发
Swift 语言: 什么是协议(Protocol)?如何实现和使用协议?
Swift 语言: 什么是协议(Protocol)?如何实现和使用协议?
41 2
|
6月前
|
缓存 Java iOS开发
OC中动态方法解析
OC中动态方法解析
26 1
|
缓存 Swift
OC版本的Moya插件网络
OC版本的Moya插件网络
|
Swift
OC与swift的数据传输
该项目主要介绍了oc与swift之间、swift内部几种常见的传值方式(属性传值、代码块传值、代理传值、通知) 如果oc与swift之间的桥接有疑问请参考:OC与swift桥接互调
182 0
OC与swift的数据传输
|
Swift
swift协议的设置和实现
swift协议的设置和实现
208 0
|
Java Go Swift
Swift里的protocol--协议
我感觉它和java或go里的接口,差不多一个意思吧。
1401 0