iOS之协议(protocol)的使用

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]);
		// 将剩下的作业数减1
		dataNum--;
		// 把作业队列整体前移一位
		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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值