您的位置:首页 > 其它

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

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

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

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

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

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

声明一个协议myprotocol

[cpp] view
plaincopyprint?

@protocol myprotocol <NSObject>  

@optional  

-(void)print:(int)value;  

//可选的方法  

  

@required  

-(int)printValue:(int)value1 andValue:(int)value2;  

//必须实现的  

  

@end  

实现这个协议

mytest.h

[cpp] view
plaincopyprint?

#import <Foundation/Foundation.h>  

#import "myprotocol.h"  

  

//实现协议 myprotocol  

@interface mytest : NSObject<myprotocol>   

{  

  

}  

- (void)showInfo;  

@end  

mytest.m

[cpp] view
plaincopyprint?

#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

[cpp] view
plaincopyprint?

#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

[cpp] view
plaincopyprint?

#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

[cpp] view
plaincopyprint?

#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

[cpp] view
plaincopyprint?

#import <Foundation/Foundation.h>  

#import "Dog.h"  

  

@interface Person : NSObject<dogBark>  

{  

  

    Dog *_dog;  

}  

  

@property (retain) Dog *dog;  

@end  

person.m

[cpp] view
plaincopyprint?

#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

[cpp] view
plaincopyprint?

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

[cpp] view
plaincopyprint?

#import <Cocoa/Cocoa.h>  

  

@interface dog : NSObject {  

    int _ID;  

    }  

@property int ID;  

  

@end  

[cpp] view
plaincopyprint?

#import "dog.h"  

  

@implementation dog  

@synthesize  ID=_ID;  

-(id)init  

{  

    self=[super init];  

    return self;  

}  

  

@end  

person类

[cpp] view
plaincopyprint?

#import <Cocoa/Cocoa.h>  

#import "dog.h"  

  

@interface person : NSObject   

{  

    dog *_mydog;  

}  

  

-(void)setDog:(dog*)aDog;  

-(id)mydog;  

-(void)callFun;  

@end  

[cpp] view
plaincopyprint?

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

[cpp] view
plaincopyprint?

#import <Cocoa/Cocoa.h>  

  

  

@interface  NSObject(myCategroy)   

-(void)callFromNSObject;  

@end  

[cpp] view
plaincopyprint?

#import "nsobject_categroy.h"  

  

  

@implementation  NSObject(myCategroy)   

-(void)callFromNSObject  

{  

    NSLog(@"I AM NSOBJECT FUNCTIONS");  

}  

@end  

主函数:

[cpp] view
plaincopyprint?

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

类别主要有三个功能:

一、利用类别分散实现

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

三、非正式协议和委托类别
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: