OC正式协议和非正式协议的区别

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

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

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

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

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

声明一个协议myprotocol

[cpp] view
plain
copyprint?

  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

[cpp] view
plain
copyprint?

  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

[cpp] view
plain
copyprint?

  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

[cpp] view
plain
copyprint?

  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

[cpp] view
plain
copyprint?

  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

[cpp] view
plain
copyprint?

  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

[cpp] view
plain
copyprint?

  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

[cpp] view
plain
copyprint?

  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

[cpp] view
plain
copyprint?

  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对象来调用这个方法。

[cpp] view
plain
copyprint?

  1. #import <Cocoa/Cocoa.h>  
  2.   
  3. @interface dog : NSObject {  
  4.     int _ID;  
  5.     }  
  6. @property int ID;  
  7.   
  8. @end  

[cpp] view
plain
copyprint?

  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类

[cpp] view
plain
copyprint?

  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  

[cpp] view
plain
copyprint?

  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类别的实现,也就是非正式协议

[cpp] view
plain
copyprint?

  1. #import <Cocoa/Cocoa.h>  
  2.   
  3.   
  4. @interface  NSObject(myCategroy)   
  5. -(void)callFromNSObject;  
  6. @end  

[cpp] view
plain
copyprint?

  1. #import "nsobject_categroy.h"  
  2.   
  3.   
  4. @implementation  NSObject(myCategroy)   
  5. -(void)callFromNSObject  
  6. {  
  7.     NSLog(@"I AM NSOBJECT FUNCTIONS");  
  8. }  
  9. @end  

主函数:

[cpp] view
plain
copyprint?

  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方法

类别主要有三个功能:

一、利用类别分散实现

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

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

时间: 2024-08-28 05:42:26

OC正式协议和非正式协议的区别的相关文章

OC正式协议和非正式协议

最近看了些关于objective-c的正式协议和非正式协议的内容,发现还是有些混乱,可能是因为还不熟悉OC,对正式协议和非正式协议的使用还不是很熟练,所以想整理一下 非正式协议,是使用类别category来实现,非正式协议是NSObject的一个类别,这样任何类的对象都可以作为委托对象来使用,它可以列出对象能够执行的所有方法,这样用来实现委托, 我们可以使用选择器来判断该非正式协议中是否有这个方法. 正式协议,是一个命名的方法列表,与非正式协议相比不同的是,它要求显示的采用协议,采用协议的方法是

Http、TCP/IP协议与Socket之间的区别

网络由下往上分为: 物理层-- 数据链路层-- 网络层-- IP协议 传输层-- TCP协议 会话层-- 表示层和应用层-- HTTP协议 1.TCP/IP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在"无差别"的网络之上. 建立起一个TCP连接需要经过"三次握手": 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态

开源领域常用的许可协议和它们之间的区别

越来越多的开发者与设计者希望将自己的产品开源,以便其他人可以在他们的代码基础上做更多事,开源社区也因此充满生机.在我们所能想到的应用领域,都有开源软件存在(象 WordPress,Drupal 这些开源CMS).然而很多人对开源许可并不了解,本文介绍开源领域常用的几种许可协议以及它们之间的区别. 什么是许可协议? 什么是许可,当你为你的产品签发许可,你是在出让自己的权利,不过,你仍然拥有版权和专利(如果申请了的话),许可的目的是,向使用你产品的人提供一定的权限. 不管产品是免费向公众分发,还是出

RTSP协议、RTMP协议、HTTP协议的区别

理论上RTSP RTMPHTTP都可以做直播和点播,但一般做直播用RTSP RTMP,做点播用HTTP.做视频会议的时候原来用SIP协议,现在基本上被RTMP协议取代了. RTSP. RTMP.HTTP的共同点.区别 共同点: 1:RTSP RTMP HTTP都是在应用应用层. 2: 理论上RTSP RTMPHTTP都可以做直播和点播,但一般做直播用RTSP RTMP,做点播用HTTP.做视频会议的时候原来用SIP协议,现在基本上被RTMP协议取代了. 区别: 1:HTTP: 即超文本传送协议(

【SSL协议】SSL协议详解

背景介绍    最近在看<密码学与网络安全>相关的书籍,这篇文章主要详细介绍一下著名的网络安全协议SSL. 在开始SSl介绍之前,先给大家介绍几个密码学的概念和相关的知识. 1.密码学的相关概念 密码学(cryptography):目的是通过将信息编码使其不可读,从而达到安全性. 明文(plain text):发送人.接受人和任何访问消息的人都能理解的消息. 密文(cipher text):明文消息经过某种编码后,得到密文消息. 加密(encryption):将明文消息变成密文消息. 解密(d

协议格式-这些协议的格式&amp;amp;quot;帧头,功能号,结束符&amp;amp;quot;根据什么而来?

问题描述 这些协议的格式"帧头,功能号,结束符"根据什么而来? 本人小白,不懂一些协议格式,比如,帧头0x15功能号0x01结束符0x0A,这些根据什么依据而来,如果我要修改格式,应该根据哪块部分来修改求各位大神赐教,尽量说的通俗明白一点, 解决方案 这都是人定的,发送方和接收方定好通讯协议 解决方案二: ppp协议帧格式UDP协议格式

FFmpeg实现监控摄像头的RTSP协议转RTMP协议直播

文章来源:http://www.cuplayer.com/player/PlayerCode/RTSP/2014/0706/1419.html     FFmpeg实现监控摄像头的RTSP协议转RTMP协议直播,我们使用的摄像头是海康的可以通过rtsp协议获取到摄像头的直播数据.所以可以通过 整理了一下要解决如下问题: 1.  摄像头的数据采集. 2.  如何将采集到的数据交给Red5处理. 3.  [FFmpeg]图文介绍windows下实现编译ffmpeg工程的详细步骤   解决方法: 1.

关于mapi、pop3协议、smtp协议的问题!请高手指点!!!

问题描述 1.请问MAPI是邮件协议还是函数接口,如果是协议的话能抓包看见吗?2.如果它是协议如何设置exchange服务器我才能抓到数据包?3.mapi和pop3协议,smtp协议有什么关系可以接发邮件不用pop3和smtp吗?4.MAPI可以优化吗?应该怎么优化? 解决方案 解决方案二:1.MAPI接口是由微软公司提供的一系列供使用者开发Mail.Scheduling.bulletinboard.communication程序的编程接口.2.3.有个imap协议,与pop3类似,也是收邮件用

内网服务器TCP协议层的协议种类单一么?

问题描述 内网服务器TCP协议层的协议种类单一么? RT,比如一台公司内网web服务器,对其每小时抓包能找出多少种协议?5个,10个,15个?发现其多少端口被占用?5个?10个?15个? 解决方案 这取决于你的网络环境所使用的应用等,使用的协议越多,自然端口越多. 解决方案二: 只要一个程序联网,就会默认占用至少一个端口,服务器上一般主要是应用服务,每个应用服务占用不同的端口 而协议指的是传输协议,相同的服务一般使用的协议都是一致的,但端口肯定是不一样的 比如,WEB服务器一般是80端口,你可以