Objective-C 【protocol-协议 的了解使用】
———————————————————————————————————————————
protocol(协议)
(1)引文:OC中的protocol和Java中的接口(interface)比较类似,Java中的接口(interface)就是一堆方法的声明(没有实现),而OC中的interface是一个类的头文件的声明,并不是真正意义上的接口,在OC中,接口是一个叫做 协议 的 protocol 来实现的。
和Java不同,protocol 可以声明一些必须实现的方法和一些选择实现的方法。(Java中如果要实现接口,就要必须实现接口中的所有方法,否则报错。 而protocol中声明的方法可以实现也可以不实现,这里其实默认也是全部都要实现的,只不过OC是弱语法语言,如果没有实现protocol中的方法,只会发出警告,而不会报错)
(2)OC中的协议(protocol):
①Protocol:就一个用途,用来声明一大堆的方法。(但是不能声明成员变量,也不能实现方法)
②只要某个类遵守了某个协议,就拥有了这个协议中的所有的 方法声明(实现还得自己去实现。如果是继承,则继承了父类的声明和实现,这和protocol是不同的)
③只要父类遵守了某个协议,那么子类也得遵守
④Protocol声明的方法可以让任何类去实现,Protocol就是协议
⑤OC不能继承多个类(遵守单继承原则),但是能够遵守多个协议。继承(:),遵守协议(< >)
⑥基协议: <NSObject> 是基协议,是最根本最基本的协议,其中声明了很多最基本的方法。
⑦协议可以遵守协议,一个协议遵守了另一个协议,就可以拥有另一份协议中的方法声明。
(3)一般定义协议是在.h文件中,而谁采用这个协议就在谁的.m文件中实现方法。
①定义协议
@protocol 协议名称 <NSObject>
//方法声明列表
@end
注意:协议默认的要采纳NSObject的协议。
②采用协议
★★★采用协议的时候要引入协议的头文件,然后再让 类/协议 去遵守协议
★某个类遵守 某个协议 或者 某些协议,一个类可以遵守其他多个协议:
@interface 类名:父类 <协议名称1,协议名称2,协议名称3>
@end
★某个协议遵守 某个协议 或者 某些协议,一个协议可以遵守其他多个协议:(协议之间的继承关系)
@protocol 协议名称 <其他协议名称1,其他协议名称2,其他协议名称3>
@end
③实现协议中的方法
在类的.m文件中实现
接下来我们用一段代码来描述上述三个操作(①②③):
★main.m★
#import <Foundation/Foundation.h>
#import "Car.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Car *car1=[[Car alloc]init];
[car1 run];
[car1 train];
}
return 0;
}
★runProtocol.h★
#import <Foundation/Foundation.h>
@protocol runProtocol <NSObject>
//runProtocol协议遵守NSObject(基协议)
-(void)run;
-(void)jump;
-(void)jump2;
@end
★toolProtocol.h★
#import <Foundation/Foundation.h>
#import "runProtocol.h" //我们引入之间创建的协议runProtocol的头文件
//协议遵守其他协议
@protocol toolProtocol <NSObject,runProtocol> //然后让toolProtocol协议去遵守NSObject和runProtocol两个协议(这里注意,NSObject是每个协议创建的时候都要遵守的)
-(void)plane;
-(void)train;
@end
★Car.h★
#import <Foundation/Foundation.h>
#import "toolProtocol.h"
//#import "runProtocol.h" //因为我们让toolProtocol协议去遵守runProtocol协议,所以只导入toolProtocol协议的头文件即可
//我们要引入我们遵守的协议的头文件
//类遵守协议
@interface Car : NSObject <toolProtocol> //引入头文件后才能第二步遵守协议。这里也是只遵守toolProtocol协议就行了,这相当于让Car类同时遵守了toolProtocol和runProtocol两个协议。
@end
★Car.m★
#import "Car.h"
@implementation Car
//第三步才是实现协议中的方法
-(void)run
{
NSLog(@"run!");
}
-(void)jump
{
NSLog(@"jump!");
}
-(void)jump2
{
NSLog(@"jump2!");
}
-(void)plane
{
NSLog(@"plane!");
}
-(void)train
{
NSLog(@"train!");
}
@end
(4)如果父类遵守一个协议,那么他的子类也相应遵守这个协议。
(5)NSObject是一个基类,同时也有NSObject这个基协议。(这个在上面的代码中已经提到)
★而且,查看源码得知:基类也是遵守基协议的。
———————————————————————————————————————————
protocol中的@required和@optional
@required和@optional 是协议方法声明中的两个至关重要的关键字,他们的作用主要控制方法是否必须要实现!
@required —— 必须实现(编译器默认是@required,若不实现,会警告)
@option —— 可以选择实现
用途在于程序员之间的交流。OC是弱语法,一旦没有写方法实现,能提醒别人知道。警告一下但是不报错,别人用你的代码的时候可以很好的提示一下。
这段知识比较简单,我用截图给大家说明一下:
我们创建了一个foodProtocol的协议,里面有@required属性的方法和@optional属性的方法。
我们让Dog类遵守foodProtocol协议。
我们选择实现其中一个@required类型的方法(drink),而其他的两个方法不实现,然后我们发现了一个警告。
警告显示eat方法在foodProtocol中声明了但是没有实现,但是却没有提示bark方法,显然原因大家已经知道了。
而这就是@required 和 @optional 关键字的用法。
———————————————————————————————————————————
protocol类型限制
(1)使用id存储对象时,对象的类型限制
格式:id <协议名称> 变量名;
如: id <Myprotocol> obj1;
(2)对象创建时类型限制
格式:类名 <协议名称> *变量名
如:Person <houseHold> *p= [ [ Student alloc ] init ];
(3)对象关联关系下,对象的类型限制
如:
@property (nonatomic,strong) id<girlFriend> girlfriend;
//创建一个girl的成员变量,表示创建出来的Person的实例对象应该拥有一个女友,而且女友需要遵守girlFriend的协议
代码:
★girlFriend★
#import <Foundation/Foundation.h>
@protocol girlFriend <NSObject>
//girlFriend必须遵守的(会做饭洗衣)
@required
-(void)cook;
-(void)washClothes;
//允许girlFriend不遵守的(有国企工作的优先)
@optional
-(void)goodJob;
@end
★Person.h★
#import <Foundation/Foundation.h>
#import "girlFriend.h"
@interface Person : NSObject
//创建一个girl的成员变量,表示创建出来的Person的实例对象应该拥有一个女友,而且女友需要遵守girlFriend的协议
//增加限制id<girlFriend>
//表示,id存储的对象必须实现了girlFriend协议
//找的女朋友,必须会洗衣做饭
@property (nonatomic,strong) id<girlFriend> girlfriend;
@end
★Person.m★
#import "Person.h"
@implementation Person
@end
★Girl.h★
#import <Foundation/Foundation.h>
#import "girlFriend.h"
@interface Girl : NSObject <girlFriend> //这里写上Girl类遵守girlFriend协议
@end
★Girl.m★
#import "Girl.h"
@implementation Girl
-(void)cook
{
NSLog(@"cook dinner~");
}
-(void)washClothes
{
NSLog(@"wash clothes~");
}
@end
★mian.m★
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Girl.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Girl *girl1=[Girl new];
Person *p1=[Person new];
Person *p2=[Person new];
p1.girlfriend=girl1; //这里不会报错,因为girl1是Girl类型的变量,所以遵守girlFriend协议,可以赋值
[p1.girlfriend cook];
[p1.girlfriend washClothes];
p1.girlfriend=p2; //这里会报错,因为p2是Person类型的,而Person并不遵守这个协议,所以无法赋值
// [p1.girlfriend cook]; //随便用一个p2来赋给p1,做p1的女朋友是不行的
}
return 0;
}
———————————————————————————————————————————
protocol的代理模式引入
MVC(三层框架)
m - model
v - view
c - controller
★代理模式概念:
传入的对象,代替当前类完成了某个功能,称为代理模式
代理模式应用场合:
①当对象A发生了一些行为,想告知对象B(让对象B成为对象A的代理对象)
②对象B想监听对象A的一些行为(让对象B成为对象A的代理对象)
③当对象A无法处理某些行为的时候(让对象B成为对象A的代理对象)
★我们可以看出,在上面的三个场合中,B需要满足协议要求的,才能帮助/代替A干某些事情。这就建立了一个代理模式应用场合。当然满足代理模式应用的场合还有许多。
下面是一个这样的程序:baby有吃东西和睡觉的方法,如果baby睡觉或者是吃饭都要去让一个人来帮助他完成(在吃东西和睡觉方法中调用另外一个对象的方法),而保姆就是那个具备照顾baby要求的人选(遵守了协议)。现在我们要求一个老师去照顾baby,帮助baby去完成吃饭睡觉的工作,但老师是不遵守协议的,然后我们要让老师也遵循这个协议去照顾baby。
形容的实在太啰嗦了,原谅我的口才不是太好。
问题的关键先建立模型,将方法写好之后再考虑协议的问题。一步一步的添加上述要求。
代码:
// babysitProtocol.h
#import <Foundation/Foundation.h>
@class Baby;
@protocol babysitProtocol <NSObject>
-(void)feedBaby:(Baby *)baby;
-(void)hongBabyToSleep:(Baby *)baby;
@end
// Baby.h
@interface Baby : NSObject
@property (nonatomic) id <babysitProtocol> bm;
@property (nonatomic) float weight;
@property (nonatomic) float height;
-(void)wantEat;
-(void)wantSleep;
@end
// Baby.m
#import "Baby.h"
#import "Baomu.h"
@implementation Baby
-(void)wantEat
{
NSLog(@"baby want eat!");
[self.bm feedBaby:self];
}
-(void)wantSleep
{
NSLog(@"baby want sleep!");
[self.bm hongBabyToSleep:self];
}
@end
// Baomu.h
#import <Foundation/Foundation.h>
#import "babysitProtocol.h"
@class Baby;
@interface Baomu : NSObject <babysitProtocol>
-(void)feedBaby:(Baby *)baby;
-(void)hongBabyToSleep:(Baby *)baby;
@end
// Baomu.m
#import "Baomu.h"
#import "Baby.h"
@implementation Baomu
-(void)feedBaby:(Baby *)baby
{
NSLog(@"Baomu feed baby!");
baby.weight+=1;
}
-(void)hongBabyToSleep:(Baby *)baby
{
NSLog(@"Baomu baby sleep!");
baby.height+=0.5;
}
@end
// Teacher.h
#import <Foundation/Foundation.h>
#import "babysitProtocol.h"
@interface Teacher : NSObject <babysitProtocol>
@end
// Teacher.m
#import "Teacher.h"
#import "Baby.h"
@implementation Teacher
-(void)feedBaby:(Baby *)baby
{
NSLog(@"Teacher feed baby!");
baby.weight+=1;
}
-(void)hongBabyToSleep:(Baby *)baby
{
NSLog(@"Teacher baby sleep!");
baby.height+=0.5;
}
@end
// main.m
//一般而言什么 类/协议 遵守另外的协议,后面的协议尖括号是紧跟着 类/协议 去写的,不要将协议的位置写错
#import <Foundation/Foundation.h>
#import "Baby.h"
#import "Baomu.h"
#import "Teacher.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Baby *baby1=[Baby new];
Baomu *baomu1=[Baomu new];
baby1.bm=baomu1;
[baby1 wantEat];
//以上四句话是非常合理的,因为baomu1是Baomu的实例对象,baomu1遵守babysitProtocol协议,所以说baby1可以拥有他,并且调用。
//但是如果写下面两句显然就有错了,因为我们并没有让Teacher类去遵守babysitProtocol这个协议。
// Teacher *teacher1=[Teacher new];
// baby1.bm=teacher1;
//那么我们应该怎么改进呢?
// 显然,我们应该让Teacher类也遵守babysitProtocol协议,然后将Baby中的bm属性设置为id类型,这样Teacher也能feedBaby和hongBabyToSleep了~
// 具体代码在各个文件中已经改变~
Baby *baby2=[Baby new];
Teacher *teacher2=[Teacher new];
baby2.bm=teacher2;
[baby2 wantSleep];
}
return 0;
}
———————————————————————————————————————————
版权声明:本文为博主原创文章,未经博主允许不得转载。
Objective-C 【protocol-协议 的了解使用】的更多相关文章
- Objective中的协议(Protocol)
Objective中的协议(Protocol) 作用: 专门用来声明一大堆方法. (不能声明属性,也不能实现方法,只能用来写方法的声明). 只要某个类遵守了这个协议.就相当于拥有这个协议中的所有的方法 ...
- Objective-C( protocol协议)
protocol 协议 protocol:用来声明方法 1.协议的定义 @protocol 协议名称 <NSObject> // 方法声明列表.... @end 2.如何遵守协议 1> ...
- ISO 基础之 (十三) protocol 协议
一 简绍 protocol,简单来说就是一系列不属于任何类的方法列表,其中声明的方法可以被任何类实现.这种模式一般称为代理(delegation)模式.通过Protocol定义各种行为,在不同的场景采 ...
- 【转】iOS开发-Protocol协议及委托代理(Delegate)传值
原文网址:http://www.cnblogs.com/GarveyCalvin/p/4210828.html 前言:因为Object-C是不支持多继承的,所以很多时候都是用Protocol(协议)来 ...
- protocol(协议)
可以用来声明一大堆方法(不能声明成员变量) 只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明 只要父类遵守了某个协议,就相当于子类也遵守了 //定义一个名叫MyProtocol的 ...
- OC语法10——@protocol协议,
参考资料:博客 @protocol,协议: OC中protocol的含义和Java中接口的含义是一样的,它们的作用都是为了定义一组方法规范. 实现此协议的类里的方法,必须按照此协议里定义的方法规范来. ...
- iOS开发-Protocol协议及委托代理(Delegate)传值
前言:因为Object-C是不支持多继承的,所以很多时候都是用Protocol(协议)来代替.Protocol(协议)只能定义公用的一套接口,但不能提供具体的实现方法.也就是说,它只告诉你要做什么,但 ...
- Tabular DataStream protocol 协议
Tabular DataStream protocol 协议 Freetds 创建过程 https://wenku.baidu.com/view/2076cbfaaef8941ea76e0576.ht ...
- DHCP (Dynamic Host Configuration Protocol )协议的探讨与分析
DHCP (Dynamic Host Configuration Protocol )协议的探讨与分析 问题背景 最近在工作中遇到了连接外网的交换机在IPv6地址条件下从运营商自动获取的DNS地址与本 ...
- SIP (Session Initiation Protocol) 协议
Session Initiation Protocol 介绍 SIP是VoIP技术最常使用的协议,它是一种应用程序层协议,可与其他应用程序层协议配合使用,以控制Internet上的多媒体通信会话. V ...
随机推荐
- Java多线程:线程死锁
发生死锁的原因通常是两个对象的锁相互等待造成的. 以下用一个实例来构造这样的情况: package basic.e_deadlock; import org.apache.log4j.Logger; ...
- js 获取cookie
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head ...
- 【JavaScript】关于JS中的constructor与prototype
最初对js中 object.constructor 的认识: 在学习JS的面向对象过程中,一直对constructor与prototype感到很迷惑,看了一些博客与书籍,觉得自己弄明白了,现在记录如下 ...
- 跟大家分享下今天所学到的PHP,虽然很基础,但是感觉也很重要
PHP:Hypertext PreProcessor(超文本预处理语言) PHP是一种服务器端语言(server-side language),服务器只发送脚本的输出,通常是HTML,PHP也可以用于 ...
- Bash脚本编程基础
为实现某个任务,将许多命令组合后,写入一个可执行的文本文件的方法,称为Shell脚本编程. 按照应用的Shell环境不同,可以将Shell脚本分为多种类型.其中最常见的是应用于Bash和Tcsh的脚本 ...
- js本地图片预览代码兼容所有浏览器
html代码 <div id="divPreview" style="width: 160px; height: 170px"><img id ...
- oracle视图总结
视图简介: 视图是基于一个表或多个表或视图的逻辑表,本身不包含数据,通过它可以对表里面的数据进行查询和修改.视图基于的表称为基表.视图是存储在数据字典里的一条select语句. 通过创建视图可以提取数 ...
- C#求所有可能的排列组合
static System.Collections.Specialized.StringCollection MakeStrings(string[] characters, int finalStr ...
- solr查询在solrconfig.xml中的配置
<requestHandler name="/select" class="solr.SearchHandler"> <lst name=&q ...
- PostgreSQL异步客户端(并模拟redis 数据结构)
以前为了不在游戏逻辑(对象属性)变更时修改数据库,就弄了个varchar字段来表示json,由服务器逻辑(读取到内存)去操作它. 但这对运维相当不友好,也不能做一些此Json数据里查询. 所以后面就用 ...