写在前面的话
在我身边的同学中,有一些同学不能正确的理解什么是协议和代理,协议和代理的关系。这篇博文总结了一些我对协议和代理的理解,这是对自己所学习的知识的一个总结,可能存在一些理解不到位的地方,请多多包涵,同时也希望这些文字能帮到一些人。
什么是协议和代理
接触过Java的同学可能会知道在Java中有一种和协议代理很相似的东西,叫做接口(interface)如果你对它有一定了解,那么学习协议和代理也会很轻松。
公司和程序员
做一个也许不是很恰当的比喻,协议就像合同,代理就是执行合同内容的人。
下面,我们来看一个故事:
有一家公司招聘了一名程序员张三,和张三签订了一份劳动合同,合同里规定了他需要完成的工作,在公司需要的时候,张三就必须完成这些工作,有时候还需要将结果反馈给公司。 |
在上面的故事中一共有四个关键点,我们来梳理一下。
- 有一家公司。
- 公司提供了一个程序员的职位。
- 来应聘这个职位的人必须签订程序员的劳动合同,并完成合同所规定的工作。
- 张三应聘上了这个职位。
类比到OC中。
这里的公司就是定义协议的类,程序员职位就是代理,劳动合同就是它定义的协议,程序员必须完成的工作是协议里规定的必须实现的方法,张三就是实现这个协议的类,张三应聘上了这个职位就是设置好了代理。
举个栗子
听完了故事,接下来就来实践一下吧
首先创建一个CommandLine Tool 工程,并创建Company 和Person两个类,它们都继承自NSObject
然后我们在Company.h 文件中声明一个协议(故事中的劳动合同)
#import <Foundation/Foundation.h>
//声明协议内容
@protocol CompanyProgrammerDelegate <NSObject>
@required//必须的
-(NSString *)doProgrammingJobWithProjectName:(NSString *)name;//根据工程的名称来完成编程工作
@optional//可选的
-(void)repairComputer;//修电脑
@end
@interface Company : NSObject
@property(nonatomic,weak)id <CompanyProgrammerDelegate> programer;//代理
-(void)doWork;//开始工作
@end
上面的代码声明了一个叫做CompanyProgrammerDelegate的协议,协议规定了实现协议的类必须完成以下要求:
- 实现一个叫做doProgrammingJobWithProjectName:的方法
- 可以选择性实现一个叫做repairComputer的方法(不是必须的,也可以不实现)
同时,我们也在Company类的interface里声明了一个叫programmer的属性,这就是我们常说的代理(公司提供的程序员职位):
@property(nonatomic,weak)id <CompanyProgrammerDelegate> programer;//代理
其中id 后面的尖括号指定了这个属性必须是实现了CompanyProgrammerDelegate协议的(必须能够完成程序员该做的工作的,签订了劳动合同的人才能在这个职位工作)。
我们也声明了一个方法表示公司开始工作。
-(void)doWork;//开始工作
然后在Company.m中实现这个方法:
-(void)doWork{
NSLog(@"开始工作");
if (self.programer){//检查代理是否已经设置(该职位是否有人)
if([self.programer respondsToSelector:@selector(doProgrammingJobWithProjectName:)])
{//如果已经设置,代理能否响应相应的方法(如果有人,这个人是不是遵守了合同,能不能完成相应的工作)
NSString * completed = [self.programer doProgrammingJobWithProjectName:@"测试工程"];
//调用代理的方法,并获得返回值。(让程序员完成他的工作,并得到结果)
NSLog(@"%@",completed);
//输出结果。
}
if([self.programer respondsToSelector:@selector(repairComputer)])
{//检查代理是否实现了可选的方法,如果实现了,则调用。
[self.programer repairComputer];
}
}
NSLog(@"工作结束");
}
好了公司有了,合同有了,职位也有了,就差一个程序员了。
接下来我们在person类中实现上面声明的协议。
在Person.h中:
#import <Foundation/Foundation.h>
#import "Company.h"//导入协议所在的头文件
@interface Person : NSObject<CompanyProgrammerDelegate>//声明将要实现的协议
@end
在Person.m中:
#import "Person.h"
@implementation Person
//实现协议中规定的必须实现的方法
-(NSString *)doProgrammingJobWithProjectName:(NSString *)name{
NSLog(@"我在编程,工程名字叫:%@",name);//完成一些工作
return [NSString stringWithFormat:@"[%@] 完成了",name];//将结果返回给调用者
}
//实现协议中规定的可选实现的方法,因为是可选的,也可以不实现。
-(void)repairComputer{
NSLog(@"我在修电脑");
}
@end
现在一切准备就绪,接下来在main.m里实例化他们:
#import <Foundation/Foundation.h>
#import "Company.h"
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person * zhangSan = [[Person alloc]init];
Company * aCompany = [[Company alloc]init];
aCompany.programer = zhangSan;//设置代理(张三应聘上了程序员职位)
[aCompany doWork];//开始工作
}
return 0;
}
运行的结果:
最后
总的来说,A把自己需要做但不能由自己完成的事情写到协议中,如果B实现了(或者叫遵守了)这个协议,就必须完成协议里规定的内容,当A需要的时候就会通过代理(A的一个属性)来调用B去完成一些事情,A不需要知道B是如何完成的,他只关心结果,而B也不需要知道A为什么要做这件事,以及A拿到结果之后会干什么,B只需要完成自己的工作返回正确的结果即可。
以上就是我对协议和代理的一些理解。