———————————————————————————————————————————

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-协议 的了解使用】的更多相关文章

  1. Objective中的协议(Protocol)

    Objective中的协议(Protocol) 作用: 专门用来声明一大堆方法. (不能声明属性,也不能实现方法,只能用来写方法的声明). 只要某个类遵守了这个协议.就相当于拥有这个协议中的所有的方法 ...

  2. Objective-C( protocol协议)

    protocol 协议 protocol:用来声明方法 1.协议的定义 @protocol 协议名称 <NSObject> // 方法声明列表.... @end 2.如何遵守协议 1> ...

  3. ISO 基础之 (十三) protocol 协议

    一 简绍 protocol,简单来说就是一系列不属于任何类的方法列表,其中声明的方法可以被任何类实现.这种模式一般称为代理(delegation)模式.通过Protocol定义各种行为,在不同的场景采 ...

  4. 【转】iOS开发-Protocol协议及委托代理(Delegate)传值

    原文网址:http://www.cnblogs.com/GarveyCalvin/p/4210828.html 前言:因为Object-C是不支持多继承的,所以很多时候都是用Protocol(协议)来 ...

  5. protocol(协议)

      可以用来声明一大堆方法(不能声明成员变量) 只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明 只要父类遵守了某个协议,就相当于子类也遵守了   //定义一个名叫MyProtocol的 ...

  6. OC语法10——@protocol协议,

    参考资料:博客 @protocol,协议: OC中protocol的含义和Java中接口的含义是一样的,它们的作用都是为了定义一组方法规范. 实现此协议的类里的方法,必须按照此协议里定义的方法规范来. ...

  7. iOS开发-Protocol协议及委托代理(Delegate)传值

    前言:因为Object-C是不支持多继承的,所以很多时候都是用Protocol(协议)来代替.Protocol(协议)只能定义公用的一套接口,但不能提供具体的实现方法.也就是说,它只告诉你要做什么,但 ...

  8. Tabular DataStream protocol 协议

    Tabular DataStream protocol 协议 Freetds 创建过程 https://wenku.baidu.com/view/2076cbfaaef8941ea76e0576.ht ...

  9. DHCP (Dynamic Host Configuration Protocol )协议的探讨与分析

    DHCP (Dynamic Host Configuration Protocol )协议的探讨与分析 问题背景 最近在工作中遇到了连接外网的交换机在IPv6地址条件下从运营商自动获取的DNS地址与本 ...

  10. SIP (Session Initiation Protocol) 协议

    Session Initiation Protocol 介绍 SIP是VoIP技术最常使用的协议,它是一种应用程序层协议,可与其他应用程序层协议配合使用,以控制Internet上的多媒体通信会话. V ...

随机推荐

  1. 一步步学Mybatis-实现单表情况下的CRUD操作 (3)

    今天这一章要紧接上一讲中的东西,本章中创建基于单表操作的CRUD与GetList操作,此示例中以Visitor表为范例,为了创建一点测试数据我们先弄个Add方法吧 继续在上次的IVisitorOper ...

  2. Android闹钟【复杂版】

    最近做闹钟,所以自己写了个Demo版本,这个程序是用listview单独的类来实现的,和activity类分开来实现的!这个是用数据库进行更新的,当闹钟设置后,闹钟图片变成闹钟的样子,闹钟取消后,图片 ...

  3. HTML的disabled属性及readonly属性

    disabled属性的input不会提交到服务器. readonly属性的input会提交到服务器.

  4. 使用iOS手势UIGestureRecognizer

    UIKit中包含了UIGestureRecognizer类,用于检测发生在设备中的手势.UIGestureRecognizer是一个抽象类,定义了所有手势的基本行为,它有下面一些子类用于处理具体的手势 ...

  5. 一步步学习PHP笔记(李炎恢瓢城web俱乐部-多用户留言系统)01

    本课:div+css实现首页效果: 开发工具:xampp + phpstorm 笔记目的:仅做记录使用,方便日后查看 代码目录结构: index.php: <?php define(" ...

  6. AutoCompleteTextView输入汉字拼音首字母实现过滤提示(支持多音字,Filterable的使用)

    AutoCompleteTextView具有输入提示的功能,但是它的这种提示不适合对股票列表的过滤,如果你玩过股票软件,就会知道只要输入股票名称的首字母或股票代码就会出现符合匹配的股票,这种过滤怎么实 ...

  7. sqlserver2008 复制,镜像,日志传输及故障转移集群区别

    一, 数据库复制 SQL Server 2008数据库复制是通过发布/订阅的机制进行多台服务器之间的数据同步,我们把它用于数据库的同步备份.这里的同步备份指的是备份服务器与主服务器进行 实时数据同步, ...

  8. xcode中没有autoSizing的设置

    转自:http://blog.sina.com.cn/s/blog_954bb2f001016oyx.html 学习Xcode的iOS编程时,可能会发现Autosizing Control不见了,其原 ...

  9. iOS企业应用Profile制作流程

    第一步:企业版iDP申请完成以后,访问iOS Dev Center:https://developer.apple.com/devcenter/ios/index.action 第二步:点击Log I ...

  10. [C.Sharp] TimeSpan的用法,获取测试程序运行时间

    TimeSpan的用法 TimeSpan是用来表示一个时间段的实例,两个时间的差可以构成一个TimeSpan实例,现在就来简单介绍一下几点重要的用法: a 先来介绍几个方法 TimeSpan.Minu ...