objective-C中的接口与泛型

先承认我是标题党,因为在obj-c的世界中,官方根本没有"接口"与"泛型"这样的说法。


不过在obj-c中有二个与之接近的概念"非正式协议(interface)"与"正式协议(protocal)"。非正式协议在obj-c中的关键字虽然也是interface,但是这个跟c#中的接口(interface)并不完全相同。
回忆一下前面学过的内容,我们定义一个类Sample时,总是会先生成一个Sample.h,代码如下:
1
2
3
4
5
6
7
8
9
#import
<Foundation/Foundation.h>
 
@interface Sample
:
NSObject {
 
}
 
-(void)
HelloWorld;
 
@end
它表明Sample类中,约定了"应该"有一个名为HelloWorld的方法(注:我这里说的是应该,而不是必须),它只是一种君子协定。
如果我们在Sample.m中,并不遵守这个约定(即:不实现这个方法),编译时xcode会给出警告,如下图。但最后还是会编译成功(即:编译器对此是睁一只眼闭一只眼,默认了Sample类的这种不忠行为)
上图中的提示:Incomplete implementation of class "Sample". 意为:Sample类并未完全实现interface中约定的方法。
这就是obj-c中的协议跟c#中的接口不一样的地方:在c#中接口是强制必须实现的,否则编译这一关就过不了,而obj-c虽然在编译时会警告,但是最终能编译通过。
正式协议(protocal)
其实就是非正式协议(interface)换了一种写法而已,看上去更正规一些,语义上更强烈一些:要求采用该协议的类,"必须"实现协议中约定的方法。但是比较娱乐的是,即使是号称正式协议,编译器在编译时,遇到不守规矩的情况,仍然只是给出警告。(当然正式协议也有它存在的意义,后面会提到)
这里我们定义一个IQuery的协议
IQuery.h
1
2
3
4
5
@protocol IQuery
 
-(void)
Query:(
NSString*)
sql;
 
@end
除了把关键字@interface换成了@protocal,其它的基本上没变化。下面定义一个类DBQuery,并采用这个正式协议
DBQuery.h
1
2
3
4
5
6
7
8
#import
<Foundation/Foundation.h>
#import
"IQuery.h"
 
@interface DBQuery
:
NSObject<IQuery>
{
 
}
 
@end
注意这里的DBQuery:NSObject<IQuery>,它表明DBQuery继承自NSObject,同时要实现接口IQuery。
DBQuery.m
1
2
3
4
5
6
7
8
9
10
#import
"DBQuery.h"
 
@implementation DBQuery
 
-(void)
Query:(
NSString *)sql
{
    NSLog(@"Query
is called. sql:%@"
,sql);
}
 
@end
当然,如果在DBQuery.m中不实现方法Query,也能编译通过,只是会收到一个警告。
也许到目前为止,你会觉得protocal跟interface比起来,都是类似的概念,protocal设计纯属多余。其实不然,protocal存在的一个重要意义在于:
正式协议(protocal)可以将业务中的方法定义剥离出来,形成一个单独的文件,这跟传统OO中的提取接口是不谋而合的。如果遇到二个系统需要交换数据,可以制定一套双方都遵守的protocal,然后这二个系统中都把这个协议文件添加到项目中,实现它即可。这一功能,非正式协议(@interface)就做不到。(不信大家可以把NSObject<IQuery>中的IQuery改成其它类的interface定义名称试试,编译根本通不过)
此外,obj-C 2.0中对正式协议还做了一些扩展,允许把正式协议中的方法标识为“必须实现(@requied)”和“可选实现(@optional)”二类,如果协议中的方法被标识为@optional,即使采用该协议的类不实现这些方法,编译器也不会给出警告。这赋予了正式协议更多的灵活性。示例如下:
1
2
3
4
5
6
7
8
9
@protocol IQuery
 
@required
-(void)
Query:(
NSString*)
sql;
 
@optional
-(void)
HelloWorld;
 
@end

有了@optional关键字以后,其实“非正式协议”在语义上完全可以被“正式协议”所取代,事实上Cocoa中的非正式协议都在逐渐被标有@optional方法的正式协议所代替。

如果你在XCode的代码中,选中NSObject,右击-->Jump to Definition,会发现NSObject其实就是一个interface或protocal

选择protocal NSObject 继续,会看到NSObject.h文件中关于protocal NSObject的定义

同样的,你还可以看到interface NSObject的定义

从这里可以看到,非正式协议的interface NSObject其实最终采用的还是正式协议protocal NSObject.

也就是说,在obj-c的OO世界中,身为万物之祖的NSObject其实也就一个"正式协议”,所以从NSObject派生出的所有类,都只是在遵守一个或多个协议而已。

另一个话题泛型

在obj-c中,一切皆为指针。前面的学习中,我们已经接触到了一种特殊的类型id,它可以认为是一种特殊的指针:可以指向任何类型的对象。id 再加上正式协议,能够达到形似c#中泛型的效果(注:只是形似,并非神似)

1
2
3
4
5
6
7
8
9
#import
<Foundation/Foundation.h>
#import
"IQuery.h"
 
@interface DBQuery
:
NSObject<IQuery>
{  
 
}
 
-(void)
test:(
id<IQuery>)
obj;
@end

注意这里的 -(void) test:(id<IQuery>) obj; 这表明test方法接受一个任意类型的对象做为参数,但是该参数对象必须实现接口IQuery(也可以说成该参数对象必须采用正式协议IQuery),是不是跟c#中的

void test(List<IQuery> obj) 长得很象?

作者:菩提树下的杨过

出处:http://yjmyzz.cnblogs.com 

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

objective-C中的"非正式协议"和“正式协议”的更多相关文章

  1. Object-C非正式协议与正式协议的区别

    Object-C非正式协议与正式协议的区别 这两个概念困扰我很久了,一直都很像搞清楚到非正式协议和正式协议有什么区别和联系,下面结合网上的资料和自己的看法谈谈这个问题. 一.非正式协议 显然这个名词是 ...

  2. Objective-C非正式协议与正式协议

    这两个概念困扰我很久了,一直都很像搞清楚到非正式协议和正式协议有什么区别和联系,下面结合网上的资料和自己的看法谈谈这个问题. 一.非正式协议 显然这个名词是相对于正式协议而言的.在解释非正式协议之前, ...

  3. OC 中 类目、延展和协议

    Category : 也叫分类,类目. *是 为没有源代码的类 扩充功能 *扩充的功能会成为原有类的一部分,可以通过原有类或者原有类的对象直接调用,并且可继承 *该方法只能扩充方法,不能扩充实例变量 ...

  4. 在网络7层协议中,如果想使用UDP协议达到TCP协议的效果,可以在哪层做文章?(QQ 为什么采用 UDP 协议,而不采用 TCP 协议实现?)

    为了解决这题,可以具体看看下面这个讨论. 解灵运工程师 185 人赞同 某次架构师大会上那个58同城做即时通信的人说:原因是因为当时没有epoll这种可以支持成千上万tcp并发连接的技术,所以他们使用 ...

  5. 理解Objective C 中id

    什么是id,与void *的区别 id在Objective C中是一个类型,一个complier所认可的Objective C类型,跟void *是不一样的,比如一个 id userName, 和vo ...

  6. 浅谈Objective—C中的面向对象特性

    Objective-C世界中的面向对象程序设计 面向对象称程序设计可能是现在最常用的程序设计模式.如何开发实际的程序是存在两个派系的-- 面向对象语言--在过去的几十年中,很多的面向对象语言被发明出来 ...

  7. B/S 架构中,网络模型的分解与协议解析

    前言 如果是C/S专业毕业的或者是学过计算机网络课程的童鞋们,相信大家都知道网络模型的划分,本文首先来聊一聊目前对于B/S结构中,网络模型分解的两种方式. 没错,相信大家看到这个图片的时候就已经明白了 ...

  8. objective C中的字符串NSStirng常用操作

    objective C中的字符串操作 在OC中创建字符串时,一般不使用C的方法,因为C将字符串作为字符数组,所以在操作时会有很多不方便的地方,在Cocoa中NSString集成的一些方法,可以很方便的 ...

  9. 网络编程基础socket 重要中:TCP/UDP/七层协议

    计算机网络的发展及基础网络概念 问题:网络到底是什么?计算机之间是如何通信的? 早期 : 联机 以太网 : 局域网与交换机 广播 主机之间“一对所有”的通讯模式,网络对其中每一台主机发出的信号都进行无 ...

随机推荐

  1. ubuntu scrapy 开发环境搭建

    我的版本是14.04 1.更新系统  ##如果系统没有换国内下载路径需要换下系统的更新下载路径 http://www.cnblogs.com/seablog/p/7043798.html sudo a ...

  2. 理想中的 PCB 文件格式

    理想中的 PCB 文件格式 因为平时写代码使用 git,在画 PCB 也使用 git 来管理 PCB 文件. 但是 PCB 文件是二进制的,所以在比较时非常麻烦. 虽然 PCB 文件可以导出 文本文件 ...

  3. RK3288 USB触摸屏无法使用,需要添加PID和VID

    RK3288  Android5.1 现象:USB 接口触摸屏插到板子上,触摸屏无法使用,有可能出现更奇葩的,同一套代码,有的板子可以用,有的板子不能用. 1.打开串口调试,插上触摸屏,读取触摸屏的 ...

  4. 安装QConfig备忘

    下载wget https://github.com/Qihoo360/QConf/archive/1.2.1.tar.gz 解压tar -zxf 1.2.1.tar.gz进入目录cd QConf-1. ...

  5. (新)解决php版本ueditor中动态配置图片URL前缀(imageurlprefix)的方法

    昨天晚上写了一篇文章<解决ueditor中没法动态配置imageurlprefix的方法>,通过修改js获取当前域名的方法,配置imageurlprefix值: 发现还是不够灵活,因为域名 ...

  6. 【备忘:待完善】nsq集群初体验

    本机的一个节点及监控与管理后台 虚拟机中的一个节点 命令: [root@vm-vagrant nsq]# nsqd --lookupd-tcp-address=192.168.23.150:4160 ...

  7. python3之es+log+date+timezone

    from dateutil.parser import parse # 使用它可以方便的将字符串解析为datetimefrom tzlocal import get_localzone # 使用它可以 ...

  8. hash一致性算法

    一致性hash算法是,1097麻省理工提出的分布式hashDHT实现算法,极倔internet的热点问题 平衡性 hash结果尽可能的分布到所有的缓存中去,缓冲空间利用率最高 单调性 保持已有的缓存能 ...

  9. java代码---------实现File的目录下创建文本文档

    总结:虽然他没教给我们很多,但是他已经很棒了 package com.a.b; import java.io.*; public class dd { public static void main( ...

  10. ActiveMQ之一--ActiveMQ入门

    MQ的消费-生产者模型的一个典型的代表,一端往消息队列中不断的写入消息,而另一端则可以读取或者订阅队列中的消息.MQ和JMS类似,但不同的是JMS是SUN JAVA消息中间件服务的一个标准和API定义 ...