iOS之协议(protocol)的使用

来源:互联网 发布:php项目技术文档 编辑:程序博客网 时间:2024/06/05 19:49

1、非正式协议

当某个类实现NSObject的该类别时,就需要实现该类别下的所有方法,这种基于NSObject定义的类别即可认为是非正式协议。

类别可以实现非正式协议,这种类别以NSObject为基础,为NSObject创建类别,创建类别时即可指定该类别应该新增的方法。

2、实例

1)定义以NSObject为基础的类别Eatable

#import <Foundation/Foundation.h>// 以NSObject为基础定义Eatable类别@interface NSObject (Eatable)- (void) taste;@end
2)NSObject派生子类FKApple

//.h#import <Foundation/Foundation.h>#import "NSObject+Eatable.h"// 定义类的接口部分@interface FKApple : NSObject@end//.m#import "FKApple.h"// 为FKApple提供实现部分@implementation FKApple- (void) taste{NSLog(@"苹果营养丰富,口味很好!");}@end
3)FKApple类的测试代码

#import <Foundation/Foundation.h>#import "FKApple.h"int main(int argc , char * argv[]){@autoreleasepool{FKApple* app = [[FKApple alloc] init];[app taste];}}
对于非正式协议,Object-C并不强制实现协议中得所有方法。



1、正式协议

基本语法

@protocol   协议名  <父协议1,父协议2>

{

//协议方法

}

  • 协议名应与类名采用相同的命名规则
  • 一个协议可以有多个直接父协议,但协议只能继承协议,不能继承类
  • 协议中定义的方法只有方法签名,没有方法实现。协议中包含的方法即可是类方法,也可以是实例方法
  • 协议里的所有方法都是公开的访问权限
2、实例
1)FKOutput协议
#import <Foundation/Foundation.h>// 定义协议@protocol FKOutput// 定义协议的方法@optional- (void) output;@required- (void) addData: (NSString*) msg;@end
2)FKProductable协议
#import <Foundation/Foundation.h>// 定义协议@protocol FKProductable// 定义协议的方法- (NSDate*) getProduceTime;@end
3)FKPrintable协议,继承自上面两个协议
#import <Foundation/Foundation.h>#import "FKOutput.h"#import "FKProductable.h"// 定义协议,继承了FKOutput、FKProductable两个协议@protocol FKPrintable <FKOutput , FKProductable>@required// 定义协议的方法- (NSString*) printColor;@end
4)实现协议类FKPrinter
#import <Foundation/Foundation.h>#import "FKPrintable.h"// 定义类的接口部分,继承NSObject,遵守FKPrintable协议@interface FKPrinter : NSObject <FKPrintable>@end

#import "FKPrinter.h"#define MAX_CACHE_LINE 10// 为FKPrinter提供实现部分@implementation FKPrinter{// 使用数组记录所有需要缓存的打印数据 NSString* printData[MAX_CACHE_LINE];// 记录当前需打印的作业数int dataNum;}- (void) output{//只要还有作业,继续打印while(dataNum > 0){NSLog(@"打印机使用%@打印:%@" , self.printColor , printData[0]);// 将剩下的作业数减1dataNum--;// 把作业队列整体前移一位for(int i = 0 ; i < dataNum ; i++){printData[i] = printData[i + 1];}}}- (void) addData: (NSString*) msg{if (dataNum >= MAX_CACHE_LINE){NSLog(@"输出队列已满,添加失败");}else{// 把打印数据添加到队列里,已保存数据的数量加1。printData[dataNum++] = msg;}}- (NSDate*) getProduceTime;{return [[NSDate alloc] init];}- (NSString*) printColor{return @"红色";}@end
5)测试代码
#import <Foundation/Foundation.h>#import "FKPrinter.h"int main(int argc , char * argv[]){@autoreleasepool{// 创建FKPrinter对象FKPrinter* printer = [[FKPrinter alloc] init];// 调用FKPrinter对象的方法[printer addData:@"疯狂iOS讲义"];[printer addData:@"疯狂XML讲义"];[printer output];[printer addData:@"疯狂Android讲义"];[printer addData:@"疯狂Ajax讲义"];[printer output];// 创建一个FKPrinter对象,当成FKProductable使用NSObject<FKProductable>* p = [[FKPrinter alloc] init];// 调用FKProductable协议中定义的方法NSLog(@"%@" , p.getProduceTime);// 创建一个FKPrinter对象,当成FKOutput使用id<FKOutput> out = [[FKPrinter alloc] init];// 调用FKOutput协议中定义的方法[out addData:@"孙悟空"];[out addData:@"猪八戒"];[out output];}}

使用协议定义变量方法:
1)NSObject<协议1,协议2...>*   变量;
2)id<协议1,协议2...>   变量;
通过协议定义的变量,在编译时,仅仅只是通过协议所遵守的协议类型,因此只能调用该协议中定义的方法。



1、正式协议与非正式协议的区别:
  • 非正式协议通过为NSObject创建类别来实现,而正式协议则直接使用@protocol创建
  • 遵守非正式协议通过继承带特定类别的NSObject来实现,而遵守正式协议则有专门的Object-C语法
  • 遵守非正式协议不要求实现协议中定义的所有方法,而遵守正式协议则必须实现协议中定义的所有方法
  • 通过使用@optional和@required关键字,正式协议可以完全替代非正式协议
2、解决正式协议必须实现协议所有方法造成灵活性不足问题
  • @optional:位于@optional关键字之后、@optional或@end之前声明的方法是可选的——实现类既可选择实现这些方法,也可不实现这些方法。
  • @required:位于@required关键字之后,@required或@end之前声明的方法时必须得——实现类必须实现这些方法。
如下:
// 定义协议@protocol FKOutput// 定义协议的方法@optional- (void) output;@required- (void) addData: (NSString*) msg;@end

0 0
原创粉丝点击