NSObject class和NSObject protocol的关系(抽象基类与协议)
【转载请注明出处】
1、接口的实现
对于接口这一概念的支持,不同语言的实现形式不同。Java中,由于不支持多重继承,因此提供了一个Interface关键词。而在C++中,通常是通过定义抽象基类的方式来实现接口定义的。
Objective-C既不支持多重继承,也没有使用Interface关键词作为接口的实现(Interface作为类的声明来使用),而是通过抽象基类和协议(protocol)来共同实现接口的。
2、接口的意义
面向对象编程中一条重要的经验法则是:对接口编程,而不是对实现编程。即一个对象想要调用另一个对象的方法,往往不会直接采取直接调用的形式。为降低耦合度考虑,通常会在调用者和被调用者中间增加一层抽象的(通常不会变动的)中间层,接口就是中间层的最通用的形式。
3、Objective-C中的接口与协议protocol
如前所述,Objective-C中使用协议protocol作为支持接口实现的关键词。
如下类A的对象想要调用类B的对象的方法:
Class A中:
- (void)doSth:(B *)b
{
[b doSth];
}
增加一个抽象的(通常不会变动的)中间层作为中介,如下:
定义一个protocol:
@protocol doSthDelegate
(void)doSth;
@end
Class A中:
- (void)doSth:(id<doSthDelegate>) delegate
{
if (delegate)
[delegate doSth];
}
4、Objective-C中的接口与抽象基类
协议protocol其实是足以支持接口的语法实现的,但对于需要频繁调用的方法来说,未免不够简洁。如在NSObject协议中声明的alloc、dealloc、retain、release和autoRelease等几乎出现在iOS开发各个角落的方法,如果都需要
if (delegate && delegate respondsToSelector:@selector(func)
{
[delegate func];
}
那就太过麻烦了。因此NSObject Class出现了。
在NSObject中对NSObject protocol中的方法都做了基本的实现,因而保证了处于NSObject派生链中的子类在调用NSObject protocol中的方法时的可靠性。写法上也变得极为简洁。
5、抽象基类和协议共存
如4中所述,抽象基类相比于协议,一方面提供了一些方法的基本实现,使得子类不需要重复实现,另一方面能够保持语法的简洁。因此,只使用协议而不使用抽象基类,是可行的,但极不方便。
而单独使用抽象基类支持接口的语法,是基本上不可行的。如SDK中的UIView及其子类,由于Objective-C的单继承限制,这些已经有基类的类,就不能使用接口了。当然,开发者自行定义的类,是可以完全依靠抽象基类进行组织的。
6、抽象基类和协议如何协作
经典范例就是标题中的NSObject class和NSObject protocol。
在Cocoa Touch中,并非所有的类都派生自NSObject,如NSProxy类(它本身是一个root class)。但是,对NSProxy和NSproxy的派生类的对象的内存控制,仍然采用alloc、dealloc、retain、release和autoRelease是很自然的想法。在不改变NSProxy基类的情况下,就只能通过协议来支持。
在NSObject协议中,声明了retain、release和autoRelease方法(alloc和dealloc在NSProxy有定义),而NSProxy实现了NSObject协议(conform to protocol NSObject),因此可以做到
[proxyObj release];
这样的调用。
7、总结
在Objective-C中,接口的支持主要由协议protocol来实现,抽象基类用于简化语法、提供通用方法的基础实现。
参考:
【1】Objective-C编程之道
【2】NSObject class and protocol
http://objectmix.com/c/177917-nsobject-class-protocol.html
【3】NSProxy Class Reference
https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSProxy_Class/Reference/Reference.html
NSObject class和NSObject protocol的关系(抽象基类与协议)的更多相关文章
- 6、面向对象以及winform的简单运用(抽象基类与接口)
抽象类与抽象方法 1.书写规范: 在类前面加上abstract关键字,就成为了抽象类:在一个方法前面加上abstract关键字,就成为了抽象方法(抽象方法不能有实现方法,直接在后面加分号) 例: ab ...
- C# 面向对象 , 抽象基类
抽象基类 关键字, abstract abstract class SSS { public void aaa() { } } 作为抽象基类, 只能在 继承关系 中 担任父类的角色,不能出现在其他地 ...
- thrift之TTransport类体系原理及源码详细解析1-类结构和抽象基类
本章主要介绍Thrift的传输层功能的实现,传输的方式多种多样,可以采用压缩.分帧等,而这些功能的实现都是相互独立,和上一章介绍的协议类实现方式比较雷同,还是先看看这部分的类关系图,如下: 由上面的类 ...
- guxh的python笔记七:抽象基类
1,鸭子类型和白鹅类型 1.1,白鹅类型 白鹅类型对接口有明确定义,比如不可变序列(Sequence),需要实现__contains__,__iter__,__len__,__getitem__,__ ...
- 【Python】【元编程】【从协议到抽象基类】
"""class Vector2d: typecode = 'd' def __init__(self,x,y): self.__x = float(x) self.__ ...
- c++之——抽象基类
在一个虚函数的声明语句的分号前加上 =0:就可以将一个虚函数变成纯虚函数,其中,=0只能出现在类内部的虚函数声明语句处.纯虚函数只用声明,而不用定义,其存在就是为了提供接口,含有纯虚函数的类是抽象基类 ...
- OOP2(虚函数/抽象基类/访问控制与继承)
通常情况下,如果我们不适用某个函数,则无需为该函数提供定义.但我们必须为每个虚函数都提供定义而不管它是否被用到了,这因为连编译器也无法确定到底会适用哪个虚函数 对虚函数的调用可能在运行时才被解析: 当 ...
- Python高级主题:Python ABC(抽象基类)
#抽象类实例 作用统一规范接口,降低使用复杂度.import abcclass Animal(metaclass = abc.ABCMeta): ##只能被继承,不能实例化,实例化会报错 @abc.a ...
- PythonI/O进阶学习笔记_3.2面向对象编程_python的继承(多继承/super/MRO/抽象基类/mixin模式)
前言: 本篇相关内容分为3篇多态.继承.封装,这篇为第二篇 继承. 本篇内容围绕 python基础教程这段: 在面向对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法.使 ...
随机推荐
- lintcode-153-数字组合 II
153-数字组合 II 给出一组候选数字(C)和目标数字(T),找出C中所有的组合,使组合中数字的和为T.C中每个数字在每个组合中只能使用一次. 注意事项 所有的数字(包括目标数字)均为正整数. 元素 ...
- xpath教程三---逐层检索和全局检索
本节主要介绍用xpath来描述html的层级关系 主要使用到的知识点如下: 单独的一个点 .,表示当前位置 两个点 ..,表示上一级父标签的位置 单独的一个斜杠 /,表示只检索下面一级 单独的两个斜杠 ...
- 【log4net】- 非常完善的Log4net详细说明
1.概述 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.本文主要是介绍如何在Visual S ...
- React 16.x & Hooks
React 16.x & Hooks Hooks https://reactjs.org/docs/hooks-intro.html https://reactjs.org/docs/hook ...
- 进程&线程间通信方式总结
一.进程间的通信方式 # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系. # 有名管道 (namedpip ...
- poj 1018 Communication System (枚举)
Communication System Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22380 Accepted: ...
- CentOS 转义字符
常用转义字符 反斜杠(\):使反斜杠后面的一个变量变为单纯的字符串. 单引号(''):转义其中所有的变量为单纯的字符串. 双引号(""):保留其中的变量属性,不进行转义处理. 反引 ...
- java 实验四
北京电子科技学院(BESTI) 实 验 报 告 课程: Java 班级:1352 姓名:黄卫 学号:201352221 成绩: ...
- Rabbitmq----基础使用
---------------rabbitmq的基础使用--------------- 查看消息队列信息 在安装好rabbitmq-server之后,启动服务 使用命令rabbitmqctl list ...
- windows内存映射文件
http://shushanyegui.duapp.com/?p=731 在描述内存映射文件之前 我们先来写一个系统通过I/O来读写磁盘文件的小程序 #include "stdafx.h&q ...