Objective-C 的正式协议和非正式协议

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

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

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

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

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

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


类别主要有三个功能:

一、利用类别分散实现

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值