温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

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

发布时间:2020-06-17 01:18:00 来源:网络 阅读:268 作者:xiesiyuana 栏目:开发技术

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

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

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

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

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

声明一个协议myprotocol

@protocol myprotocol <NSObject> @optional -(void)print:(int)value; //可选的方法  @required -(int)printValue:(int)value1 andValue:(int)value2; //必须实现的  @end

实现这个协议

mytest.h

#import <Foundation/Foundation.h> #import "myprotocol.h"  //实现协议 myprotocol @interface mytest : NSObject<myprotocol>  {  } - (void)showInfo; @end 
mytest.m

#import "mytest.h"  @implementation mytest -(void)showInfo { 	NSLog(@"I am in showInfo"); }  //实现协议必须实现的 -(int)printValue:(int)value1 andValue:(int)value2 { 	NSLog(@"print value1 %d,value2 %d",value1,value2); 	return 0; }  //实现可选的 -(void)print:(int)value { 	NSLog(@"print value is %d",value); }  @end 
使用这个协议main.m

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

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

dog.h

#import <Foundation/Foundation.h> @protocol dogBark;  @interface Dog : NSObject { 	int _ID; 	NSTimer *timer; 	int barkCount; 	id <dogBark> delegate;		//存放狗的主人 	 } @property int ID; @property (assign)id <dogBark> delegate;  @end  //定义一个人和狗通讯的协议 protocol @protocol dogBark<NSObject> -(void)bark:(Dog*)thisDog count:(int)count;  @end
dog.m

#import "Dog.h"   @implementation Dog @synthesize ID=_ID; @synthesize delegate; -(id)init { 	if(self = [super init]){ 		//创建一个定时器user,每隔1.0s 就调用updateTimer:nil,并传递一个参数nil 		timer=[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:)  userInfo:nil repeats:YES]; 		 	} 	return self; }  -(void) updateTimer:(id)arg   { 	  barkCount++; 	  NSLog(@"dog bar %d",barkCount); 	  //调用主人delegate的bark:count方法,  	  [delegate bark:self count:barkCount]; //回调机制   }  @end

person.h

#import <Foundation/Foundation.h> #import "Dog.h"  @interface Person : NSObject<dogBark> {  	Dog *_dog; }  @property (retain) Dog *dog; @end 
person.m

#import "Person.h"  @implementation Person @synthesize dog=_dog; -(void)setDog:(Dog*)aDog { 	if(_dog!=aDog){ 		[_dog release]; 		_dog=[aDog retain]; 		// 通知dog的主人是当前人,self 		[_dog setDelegate:self]; 		 	} }  //当狗叫的时候,让狗来调用人的方法 //这个方法来源于dogBark协议,Person类来实现 -(void)bark:(Dog*)thisDog count:(int)count { 	NSLog(@"Person bark: this dog %d bark %d",[thisDog ID],count); }  -(void)dealloc { 	self.dog=nil; 	[super dealloc]; }  @end 
主函数mian.m

#import <Foundation/Foundation.h> #import "Dog.h" #import "Person.h"   int main (int argc, const char * argv[]) {     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];      // insert code here...     NSLog(@"Hello, World!"); 	Person *xiaoli = [[Person alloc]init]; 	Dog *dog=[[Dog alloc]init]; 	[dog setID:10]; 	[xiaoli setDog:dog]; 	[dog release]; 	//程序循环在这里 	while (1) { 		[[NSRunLoop currentRunLoop]run]; 	} 	[xiaoli release]; 	     [pool drain];     return 0; } 

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

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

#import <Cocoa/Cocoa.h>  @interface dog : NSObject { 	int _ID; 	} @property int ID;  @end
#import "dog.h"  @implementation dog @synthesize  ID=_ID; -(id)init { 	self=[super init]; 	return self; }  @end 
person类

#import <Cocoa/Cocoa.h> #import "dog.h"  @interface person : NSObject  { 	dog *_mydog; }  -(void)setDog:(dog*)aDog; -(id)mydog; -(void)callFun; @end
#import "person.h" #import "nsobject_categroy.h"  @implementation person  -(void)setDog:(dog*)aDog { 	if (_mydog!=aDog) { 		[_mydog release]; 		_mydog=[aDog retain]; 	} }  -(id)mydog{ 	return _mydog; }  -(void)callFun{ 	NSLog(@"call Fun!"); 	[_mydog callFromNSObject]; }  -(void)dealloc{ 	[self setDog:nil]; 	[super dealloc]; } @end
NSObject类别的实现,也就是非正式协议
#import <Cocoa/Cocoa.h>   @interface  NSObject(myCategroy)  -(void)callFromNSObject; @end 
#import "nsobject_categroy.h"   @implementation  NSObject(myCategroy)  -(void)callFromNSObject { 	NSLog(@"I AM NSOBJECT FUNCTIONS"); } @end 
主函数:

#import <Foundation/Foundation.h> #import "person.h" #import "dog.h"  int main (int argc, const char * argv[]) {     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];      // insert code here...     NSLog(@"Hello, World!"); 	dog *d=[[dog alloc]init]; 	[d setID:10]; 	person *p=[[person alloc]init]; 	[p setDog:d]; 	[p callFun]; 	[p release];     [pool drain];     return 0; } 
这样就会调用callFromNSObject方法


类别主要有三个功能:

一、利用类别分散实现

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

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












向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI