在.NET中有接口的概念,接口主要用于定义规范,定义一个接口关键字使用interface。而在Object C 中@interface是用于定义一个类的,这个和.NET中有点差别。在Object C中有一个协议(protocol) 的概念,这个和.NET中的interface类似。

  协议(Protocol) 在列出的方法在本类中并没有相应实现,而是别的类来实现这些方法,而定义协议必须使用protocol关键字。

  一. 如何定义protocol的定义

    如何使用XCode新建一个协议.h 文件

定义协议代码如下:

#import <Foundation/Foundation.h>

@protocol ProtocolCom <NSObject>

@required
-(void) eat; @optional
-(void) write; @end

定义协议代码

    从以上代码可以看到,我们可以了解到定义一个协议基本如下结构:

    @protocol protocolName<NSObject>

    @required

    //方法声明

    @optional

    //方法声明

    .......

    @end

从刚才的代码中,定义了一个名为ProtocolCom的协议,其中有两个方法 eat ,write;  上面也提到过了,protocol相当于.net中的interface 接口,接口就是用于定义规则的,但是Object C中的协议和.NET中的interface还是有点区别的,这里就涉及到@required,@optional 。 这两个标注在方法上面是有特殊含义的,这个后面详细说明。

#import <Foundation/Foundation.h>

@protocol ProtocolCom 

@required
-(void) eat; @optional
-(void) write; @end

修改协议代码

    从上面修改的代码对比来看,在协议定义后面缺少了<NSObject> ,这段代码仍然能够正常运行,其实<NSObject>也本身可以理解为ProtocolCom要遵循NSObject 协议,这个和.NET中一个类如果没有显示指定继承哪个类,那么默认就是继承的Object类的道理是一样的,所以这里可以省略。

    这里我在定义一个协议MyProtocol,这个协议必须遵循协议ProtocolCom协议。刚才上面已经了解到了协议后面跟<NSObject>,道理一样如果MyProtocol要遵循协议ProtocolCom就是用此种方式来实现,具体代码如下:

#import <Foundation/Foundation.h>
#import "ProtocolCom.h" @protocol MyProtocol <ProtocolCom> @required
-(void) setname; @optional
-(void) setage; @end

协议的"继承"

    在Object C 协议中并不习惯说继承,而是是用遵从或者遵循,比如A协议遵循B协议。这里专业上得术语可能不太准确,姑且这么说,先理解意思。

    然后我们是用一个新的类来实现协议MyProtocol中的所有方法。

#import <Foundation/Foundation.h>
#import "MyProtocol.h" @interface Student : NSObject<MyProtocol> @end -------------------------------------------
#import "Student.h" @implementation Student -(void) write{
NSLog(@"write");
} -(void) eat{
NSLog(@"eat");
} -(void) setage{
NSLog(@"Student---setage");
} -(void) setname{
NSLog(@"Student----setname");
} @end

实现协议代码

    从以上代码可以看出类Student实现了协议MyProtocol,因为协议MyProtocol遵循协议ProtocolCom,所以协议MyProtocol有四个方法。所以在Student类中可以实现四个方法。

  二. 协议相关约束

    @required 用于表示协议中该方法必须在类中实现,默认[如果不加则默认为@required]

    @optional 用于表示协议中该方法在类中可以选择实现

    看到这里貌似比.NET中的要高级点,.NET中interface定义的所有方法在子类中都必须实现。如果用@required标识的方法在子类中没有实现那么编译编译会报错,提示该方法必须实现。而@optional则不会。下面这段代码就会存在问题:

#import "Student.h"
@implementation Student
-(void) write{
NSLog(@"write");
}
-(void) eat{
NSLog(@"eat");
}
-(void) setage{
NSLog(@"Student---setage");
}
@end

未能实现所有@required标识的方法

    

  三. 同时遵循多个协议

    在.NET中一个类也可以实现多个接口,在Object C中同样如此,一个类可以实现遵循多个接口,基本语法如下:

    @interface className:parentName<ProtocolName1,ProtocolName2,...>

    ......

    @end

    虽然上面简单了点,但是还是能够看明白表达的意思,下面看一段代码说明:

    这里从新定义一个新的协议NewProtocol,里面有一个必须实现的方法getname

#import <Foundation/Foundation.h>
@protocol NewProtocol <NSObject>
@required
-(NSString*) getname;
@end

NewProtocol协议定义

    然后从新定义一个新的类Children,这个类必须遵循协议NewProtocol和协议MyProtocol ,具体代码如下:

#import <Foundation/Foundation.h>
#import "MyProtocol.h"
#import "NewProtocol.h" @interface Children : NSObject<MyProtocol,NewProtocol> @end

Children.h 遵循两个协议

    在Children.m代码中要实现两个协议中必须实现的方法

#import "Children.h"

@implementation Children

-(void) eat{
NSLog(@"eat");
} -(void) setname{
NSLog(@"Student--setname");
} -(NSString*) getname{
return @"qingyuan";
}
@end

Children.m实现两个协议代码

    下面使用测试代码,看看一个类遵循两个协议的效果:

Children *child=[[Children alloc] init];
NSString *name=[child getname];
NSLog(@"name=%@",name);
[child eat];
[child setname];

测试代码

    在上面的代码中可以正常运行,但是要注意如果可选择实现的方法没有去实现,而在这里去调用的话会报错。

  四. 正式协议和非正式协议

    说道正式协议和非正式协议,其实只要理解两个关键字@interface 和 @protocol 。先看看下面一个列子

#import <Foundation/Foundation.h>
#import "MyProtocol.h"
#import "NewProtocol.h" @interface Children : NSObject<MyProtocol,NewProtocol> -(void) love; @end

在@interface 定义一个新方法

    在Children.h中定义了一个新的方法love,之前我们也一直这样写的,没有任何问题。再看下面一段代码

#import "Children.h"

@implementation Children

-(void) eat{
NSLog(@"eat");
} -(void) setname{
NSLog(@"Student--setname");
} -(NSString*) getname{
return @"qingyuan";
}
@end

Children.m实现的代码

    使用编译器编辑,代码并没有报错。在Children.m中没有love方法的实现。 这个和我们之前所见到的代码似乎有点不一样啊,有点不理解,理论上Children.m中应该实现love方法的。

    上面看到的这种情况,就好比Protocol中的@optional方法,是可以选择实现的,其实我们就称作@interface Children : NSObject 就是一个非正式协议。

刚才也注意到了,那是不是Protocol中的@optional标识的方法也就是非正式协议呢。在这里网络上有些争议,个人也没有完全明白,但是个人理解这个还是不一样的。@protocol是一种既定的规则,如果要做就必须遵循这种规则,而@interface有点象描述,用于描述类是干什么的. 而两者因为都可选择实现其他的方法,所以感觉有点类似。

  五. 协议总结

    Object C中有点特殊的时协议不引用任何类,任何类都可以实现已经定于好的协议。

bool flag1=[child conformsToProtocol:@protocol(NewProtocol)];
NSLog(@"%d",flag1); bool flag2=[child conformsToProtocol:@protocol(MyProtocol)];
NSLog(@"%d",flag2); bool flag3=[child conformsToProtocol:@protocol(ProtocolCom)];
NSLog(@"%d",flag3);

判断某个类是否遵循协议

    从以上代码可以看得出,conformsToProtocol 方法用于判断某个类是否遵循某个协议,返回值为bool类型,即使协议是通过"继承"过来的也可以。

  本文到此结束,学习笔记可能有诸多问题,望请牛人勿喷,菜鸟的学习需要鼓励!

Object C学习笔记15-协议(protocol)的更多相关文章

  1. Object C学习笔记24-关键字总结

    学习Object C也有段时间了,学习的过程中涉及到了很多Object C中的关键字,本文总结一下所涉及到的关键字以及基本语法. 1.  #import #import <> 从syste ...

  2. Object C学习笔记24-关键字总结(转)

    学习Object C也有段时间了,学习的过程中涉及到了很多Object C中的关键字,本文总结一下所涉及到的关键字以及基本语法. 1.  #import #import <> 从syste ...

  3. Objective-C学习笔记 利用协议实现回调函数

    来源:http://mobile.51cto.com/iphone-278354.htm Objective-C学习笔记 利用协议实现回调函数是本文要介绍的内容,主要是实现一个显示文字为测试的视图,然 ...

  4. Object C学习笔记22-#define 用法

    上一篇讲到了typedef 关键字的使用,可以参考文章 Object C 学习笔记--typedef用法 .而在c中还有另外一个很重要的关键字#define. 一. #define 简介 在C中利用预 ...

  5. Object C学习笔记21-typedef用法

    在上一章的学习过程中遇到了一个关键字typedef,这个关键字是C语言中的关键字,因为Object C是C的扩展同样也是支持typedef的. 一. 基本作用 typedef是C中的关键字,它的主要作 ...

  6. Object C学习笔记18-SEL,@ selector,Class,@class

    本章是对上一章<<Object C学习笔记17-动态判断和选择器>>的一点补充,所以比较简单点. 一. SEL 类型 在上一篇介绍了几个方法,都只是介绍了其使用方式但是没有具体 ...

  7. Object C学习笔记17-动态判断和选择器

    当时学习Object C的时被人鄙视了一顿,说使用.NET的思想来学Object C就是狗屎:不过也挺感谢这位仁兄的,这让我学习的时候更加的谨慎.今天的学习笔记主要记录Object C中的动态类型相关 ...

  8. Ext.Net学习笔记15:Ext.Net GridPanel 汇总(Summary)用法

    Ext.Net学习笔记15:Ext.Net GridPanel 汇总(Summary)用法 Summary的用法和Group一样简单,分为两步: 启用Summary功能 在Feature标签内,添加如 ...

  9. SQL反模式学习笔记15 分组

    目标:查询得到每组的max(或者min等其他聚合函数)值,并且得到这个行的其他字段 反模式:引用非分组列 单值规则:跟在Select之后的选择列表中的每一列,对于每个分组来说都必须返回且仅返回一直值. ...

随机推荐

  1. 04_最长上升子序列问题(LIS)

    来源:刘汝佳<算法竞赛入门经典--训练指南> P60 问题6: 问题描述:给定n个整数a1,a2,...,an,按从左到右的顺序选出尽量多的整数,组成一个上升子序列(子序列可以理解为:删除 ...

  2. mysql存储过程procedure

    传送门 http://www.blogjava.net/sxyx2008/archive/2009/11/24/303497.html ) ); DROP PROCEDURE IF EXISTS ju ...

  3. js制作倒计时效果

    该程序可以计算任意指定的两个日期中间的差值. 本例子的指定日期是2017年1月1日,当前时间是2016年10月21日:计算它们之间的差值,在网页上显示如图所示: 关键部分代码: var nowtime ...

  4. 匈牙利算法 cojs.tk 搭配飞行员

    cojs.tk  搭配飞行员 ★★☆   输入文件:flyer.in   输出文件:flyer.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述]     飞行大队有若干个 ...

  5. Trie树 & 01Trie

    指针版 #define MAXNUM 26 //定义字典树结构体 typedef struct Trie { bool flag;//从根到此是否为一个单词 Trie *next[MAXNUM]; } ...

  6. codeforces 616E Sum of Remainders (数论,找规律)

    E. Sum of Remainders time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  7. 2D Tookit (一) 精灵切割

    Sprite Dicing 精灵切割 图一:原图 Diced 设置   Diced[切割]对比图 文档 http://www.2dtoolkit.com/docs/latest/advanced/sp ...

  8. Unity开发 资源准备

    开发环境准备 插件资源 当有喜欢的资源,选择去泽国社区和纳金网下载,仅用于学习目的. Fbx查看器 下载版本对应的FBX插件 比如:fbx20133_quicktime_win.exe 对应Quick ...

  9. [本人开发的游戏] Discuz网页动物园插件1.0Beta发布!让积分流动起来!

        插件发布 插件名称: DZ网页动物园插件 插件来源: 原创插件 适用版本: Discuz! X3 语言编码: GBK简体 UTF8简体 BIG5繁体 UTF8繁体  最后更新时间: 2014- ...

  10. IO流的练习5 —— 读取文件中的字符串,排序后写入另一文件中

    需求:已知s.txt文件中有这样的一个字符串:“hcexfgijkamdnoqrzstuvwybpl” 请编写程序读取数据内容,把数据排序后写入ss.txt中. 分析: A:读取文件中的数据 B:把数 ...