OC正式协议和非正式协议的区别
最近看了些关于objective-c的正式协议和非正式协议的内容,发现还是有些混乱,可能是因为还不熟悉OC,对正式协议和非正式协议的使用还不是很熟练,所以想整理一下
非正式协议,是使用类别category来实现,非正式协议是NSObject的一个类别,这样任何类的对象都可以作为委托对象来使用,它可以列出对象能够执行的所有方法,这样用来实现委托, 我们可以使用选择器来判断该非正式协议中是否有这个方法。
正式协议,是一个命名的方法列表,与非正式协议相比不同的是,它要求显示的采用协议,采用协议的方法是在类的@interface声明中列出协议的名称,此时,实现协议的类应该遵守协议,承诺实现协议中的所有方法,否则编译器将会发出警告。
协议类似于C++的纯虚函数,协议只有声明,没有实现,用来在子类中实现,协议中的方法有两类属性,@required和@optional两种,@required属性的要求实现协议的类必须要实现这种方法,而@optional属性的方法则不要求,如果不确定协议是否被实现,可以使用respondsToSelector:@select()来判断。
下面是一个协议的声明和实现实例代码:
声明一个协议myprotocol
- @protocol myprotocol <NSObject>
- @optional
- -(void)print:(int)value;
- //可选的方法
- @required
- -(int)printValue:(int)value1 andValue:(int)value2;
- //必须实现的
- @end
实现这个协议
mytest.h
- #import <Foundation/Foundation.h>
- #import "myprotocol.h"
- //实现协议 myprotocol
- @interface mytest : NSObject<myprotocol>
- {
- }
- - (void)showInfo;
- @end
mytest.m
- #import "mytest.h"
- @implementation mytest
- -(void)showInfo
- {
- NSLog(@"I am in showInfo");
- }
- //实现协议必须实现的
- -(int)printValue:(int)value1 andValue:(int)value2
- {
- NSLog(@"print value1 %d,value2 %d",value1,value2);
- return 0;
- }
- //实现可选的
- -(void)print:(int)value
- {
- NSLog(@"print value is %d",value);
- }
- @end
使用这个协议main.m
- #import <Foundation/Foundation.h>
- #import "mytest.h"
- #import "myprotocol.h"
- int main (int argc, const char * argv[]) {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- // insert code here...
- NSLog(@"Hello, World!");
- mytest *test=[[mytest alloc]init];
- [test showInfo];
- [test printValue:20 andValue:30];
- //print协议是可选的,所以在用之前一定要判断是否实现了,不然可能会出错,使用下面的方法
- // [test print:20];
- SEL sel=@selector(print:);
- if([test respondsToSelector:sel]){
- [test print:11];
- }
- //用协议的方式实现
- id<myprotocol> protocol =[[[mytest alloc]init]autorelease];
- [protocol showInfo];
- [protocol printValue:200 andValue:300];
- if([protocol respondsToSelector:@selector(print:)]){
- [protocol print:111];
- }
- [test release];
- [pool drain];
- return 0;
- }
下面介绍使用正式协议来实现代理,或者叫委托,委托是一中推向,另一个类的对象会要求委托对象来执行它的某些操作。
下面的例子,有一个dog类,一个person类,每个person对象有一个狗,这条狗仅仅属于这个主人,狗会定时的通知主人,也就是调用person类的一些方法,这样在狗的类中就需要一个person的代理,要求主人调用一些方法,机制类似回调,如下:
dog.h
- #import <Foundation/Foundation.h>
- @protocol dogBark;
- @interface Dog : NSObject {
- int _ID;
- NSTimer *timer;
- int barkCount;
- id <dogBark> delegate; //存放狗的主人
- }
- @property int ID;
- @property (assign)id <dogBark> delegate;
- @end
- //定义一个人和狗通讯的协议 protocol
- @protocol dogBark<NSObject>
- -(void)bark:(Dog*)thisDog count:(int)count;
- @end
dog.m
- #import "Dog.h"
- @implementation Dog
- @synthesize ID=_ID;
- @synthesize delegate;
- -(id)init
- {
- if(self = [super init]){
- //创建一个定时器user,每隔1.0s 就调用updateTimer:nil,并传递一个参数nil
- timer=[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];
- }
- return self;
- }
- -(void) updateTimer:(id)arg
- {
- barkCount++;
- NSLog(@"dog bar %d",barkCount);
- //调用主人delegate的bark:count方法,
- [delegate bark:self count:barkCount]; //回调机制
- }
- @end
person.h
- #import <Foundation/Foundation.h>
- #import "Dog.h"
- @interface Person : NSObject<dogBark>
- {
- Dog *_dog;
- }
- @property (retain) Dog *dog;
- @end
person.m
- #import "Person.h"
- @implementation Person
- @synthesize dog=_dog;
- -(void)setDog:(Dog*)aDog
- {
- if(_dog!=aDog){
- [_dog release];
- _dog=[aDog retain];
- // 通知dog的主人是当前人,self
- [_dog setDelegate:self];
- }
- }
- //当狗叫的时候,让狗来调用人的方法
- //这个方法来源于dogBark协议,Person类来实现
- -(void)bark:(Dog*)thisDog count:(int)count
- {
- NSLog(@"Person bark: this dog %d bark %d",[thisDog ID],count);
- }
- -(void)dealloc
- {
- self.dog=nil;
- [super dealloc];
- }
- @end
主函数mian.m
- #import <Foundation/Foundation.h>
- #import "Dog.h"
- #import "Person.h"
- int main (int argc, const char * argv[]) {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- // insert code here...
- NSLog(@"Hello, World!");
- Person *xiaoli = [[Person alloc]init];
- Dog *dog=[[Dog alloc]init];
- [dog setID:10];
- [xiaoli setDog:dog];
- [dog release];
- //程序循环在这里
- while (1) {
- [[NSRunLoop currentRunLoop]run];
- }
- [xiaoli release];
- [pool drain];
- return 0;
- }
使用非正式协议也可以实现委托,前面讲非正式协议是使用类别来实现的,
同样的是一个dog类,一个person类,person类有一条狗,再实现一个NSObject的类别,在类别中实现一个方法,通过dog对象来调用这个方法。
- #import <Cocoa/Cocoa.h>
- @interface dog : NSObject {
- int _ID;
- }
- @property int ID;
- @end
- #import "dog.h"
- @implementation dog
- @synthesize ID=_ID;
- -(id)init
- {
- self=[super init];
- return self;
- }
- @end
person类
- #import <Cocoa/Cocoa.h>
- #import "dog.h"
- @interface person : NSObject
- {
- dog *_mydog;
- }
- -(void)setDog:(dog*)aDog;
- -(id)mydog;
- -(void)callFun;
- @end
- #import "person.h"
- #import "nsobject_categroy.h"
- @implementation person
- -(void)setDog:(dog*)aDog
- {
- if (_mydog!=aDog) {
- [_mydog release];
- _mydog=[aDog retain];
- }
- }
- -(id)mydog{
- return _mydog;
- }
- -(void)callFun{
- NSLog(@"call Fun!");
- [_mydog callFromNSObject];
- }
- -(void)dealloc{
- [self setDog:nil];
- [super dealloc];
- }
- @end
NSObject类别的实现,也就是非正式协议
- #import <Cocoa/Cocoa.h>
- @interface NSObject(myCategroy)
- -(void)callFromNSObject;
- @end
- #import "nsobject_categroy.h"
- @implementation NSObject(myCategroy)
- -(void)callFromNSObject
- {
- NSLog(@"I AM NSOBJECT FUNCTIONS");
- }
- @end
主函数:
- #import <Foundation/Foundation.h>
- #import "person.h"
- #import "dog.h"
- int main (int argc, const char * argv[]) {
- NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
- // insert code here...
- NSLog(@"Hello, World!");
- dog *d=[[dog alloc]init];
- [d setID:10];
- person *p=[[person alloc]init];
- [p setDog:d];
- [p callFun];
- [p release];
- [pool drain];
- return 0;
- }
这样就会调用callFromNSObject方法
类别主要有三个功能:
一、利用类别分散实现
二、利用类别创建前向引用,可以实现私有函数
三、非正式协议和委托类别
OC正式协议和非正式协议的区别相关推荐
- OC的正式协议和非正式协议
最近看了些关于objective-c的正式协议和非正式协议的内容,发现还是有些混乱,可能是因为还不熟悉OC,对正式协议和非正式协议的使用还不是很熟练,所以想整理一下 非正式协议,是使用类别catego ...
- OC正式协议和非正式协议
1.概念 非正式协议,非正式协议是NSObject类(包括它的子类)的类别,其所有的子类都含蓄地接受了这个协议.非正式协议中的方法是否实现都是可选的,因此在调用非正式协议中的方法之前,需要去检查对象类 ...
- OC中的非正式协议与正式协议的区别
声明:以下内容转自:http://blog.csdn.net/wzzvictory/article/details/9295317# 这两个概念困扰我很久了,一直都很像搞清楚到非正式协议和正式协议有什 ...
- Object-C非正式协议与正式协议的区别
Object-C非正式协议与正式协议的区别 Object-C非正式协议与正式协议的区别 - braddoris的专栏 - 博客频道 - CSDN.NET http://blog.csdn.net/br ...
- 非正式协议和正式协议的区别
这两个概念困扰我很久了,一直都很像搞清楚到非正式协议和正式协议有什么区别和联系,下面结合网上的资料和自己的看法谈谈这个问题. 一.非正式协议 显然这个名词是相对于正式协议而言的.在解释非正式协议之前, ...
- 非正式协议与正式协议的区别
正式和非正式协议 协议有两种类型-正式协议和非正式协议: 非正式协议是NSObject类的范畴类(范畴类是语言特征.通过它,您无需子类化就向某个类增加方法),这意味着几乎所有的对象都是非正式协议的采纳 ...
- Objective-C非正式协议与正式协议
为什么80%的码农都做不了架构师?>>> 类别与类扩展的区别: ①类别中只能增加方法: ②是的,你没看错,类扩展不仅可以增加方法,还可以增加实例变量(或者合成属性),只是该实例 ...
- 2016 - 2- 2 非正式协议与正式协议
在重温<OBJC编程基础>这本书时,对于非正式协议的感觉非常陌生,阅读了一篇王中周的博客,结合自己在书中阅读的内容,做一些总结. 一.非正式协议 显然这个名词是相对于正式协议而言的.在解释 ...
- Objective-C(八、正式协议Protocol,非正式协议informal protocol)——iOS开发基础
结合之前的学习笔记以及参考<Objective-C编程全解(第三版)>,对Objective-C知识点进行梳理总结.知识点一直在变,只是作为参考,以苹果官方文档为准~ 八.正式协议和非正式 ...
最新文章
- Ubuntu 18.x 环境下mysql创建用户并更改用户权限
- SAP HANA里执行SQL语句的两种方式
- python运行程序的快捷键_在Python集成开发环境中,可使用快捷键()运行程序。...
- java从键盘上录入任何整数,输出该整数的阶乘
- mysql完整性约束命名_第5章--MySQL索引与完整性约束.ppt
- 「leetcode」617. 合并二叉树:【三种递归】【一种迭代】详解
- C#关键字=四六级核心词汇
- android studio for android learning (六)在布局中常使用的单位
- radius服务器连接无线网络,验证RADIUS服务器连接用测验AAA RADIUS命令
- Stata:图示交互效应-调节效应
- Django-Docker容器化部署:Django-Docker-MySQL-Nginx-Gunicorn云端部署
- BUUCTF中web方向题目记录(二)
- 一款对话网页游戏-对话部分
- SAP ABAP-获取屏幕字段数据
- 38个优秀博客站点推荐
- vue-public文件夹
- javascript 在页面显示xxxx年xx月xx日
- 【前端知识之JS】BOM的理解
- Game boy模拟器(8):中断
- 和包支付的钱哪里来_和包支付钱从哪里来的
热门文章
- ROS Couldn‘t find executable named xxx.py问题
- 大话设计模式——饕餮盛宴
- Spring Boot整合Freemarker
- MATLAB之拉氏变换
- Python+NumPy中的diag函数(简易理解)
- 京东出王炸,地下物流要来了!以后快递直接从管道送到家
- 中国科学技术大学计算机2020,中国科学技术大学2020年第七届计算机科学暑期夏令营报名通知...
- mmse评估量表_简易精神状态评价量表(MMSE)
- 如何提取pcap文件中的TCP流
- 2020年卫星行业研究报告