开放封闭原则(OCP)就是,“对扩展开放,对更改封闭”。是所有面向对象设计的一个核心宗旨。感兴趣的可以看百度百科的一些解释:http://baike.baidu.com/view/2493421.htm

在用Objective C进行开发的时候,OCP当然也是宗旨。利用继承,多态是一个很好的保持OCP的办法,也是最常见的一种方法。Objective C还支持另外两种语法来支持OCP:Protocol和Category。(想要了解Objective c语法的可以看这里:http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html)。

Protocol只能定义一套接口,而不能提供实现,变相的也是一种Abstract class的实现方式(oc 语法上本身不支持抽象基类)。Category可以为类提供额外的接口和实现。那么到底三者(继承, Protocol,Category)在使用上到底有什么本质的区别呢?在我看来,protocol的作用是为一些列类仅仅提供一套公用的接口,而完全没 有办法也没可能去提供具体的一些实现情况;category则是为一个已有的类提供一些额外的接口和具体实现;而继承则基于两者之间,既可以想 protocol一样提供只是纯粹提供接口,也可以像Category一样提供完整的实现,而且继承还能对类以后的功能进行改写,所以说继承的力量是最强 大的。那么具体在使用的时候各自都适合什么样的情况呢?

  1. Protocol是定义行为而不管谁去怎么实现,这是一种比较洒脱和不负责的情况,就好像在外包项目中的客户一样,他只是他需要什么什么东西,具体实现他不会也不能给出一样。delegate datasource这样的就用protocol实现比较好
  2. Category是对一个功能完备的类的一种补充,就像是一个东西的主要基本功能都完成了,可以用category为这个类添加不同的组件,使得 这个类能够适应不同情况的需求(但是这些不同需求最核心的需求要一致)。找个就像你已经有了一辆能够开动的汽车一样,我们可以用Category为你的汽 车添加各种之前没有的功能,最后让这辆汽车变成超级跑车一样。
  3. 当某个类非常大的时候,Category可以按不同的功能将类的实现分在不同的模块中实现。
  4. 继承则是都可以完成上面的工作,但是继承有很大的代价问题,一是通过继承来进行扩展是一种耦合很高的行为,对父类可以说是完全依赖;二是继承由于 对父类依赖,所以开发代价相对大,要求对父类的工作流程相对熟悉;三是继承体系如果太复杂会导致整个系统混乱,难以维护。所以在能够用上面两种方法完成扩 展的时候,就千万不要使用继承。什么情况才是迫不得已要使用继承呢?那就是如果你既想提供一系列接口的定义,同时又想提供一些但是又不能提供全部的实现的 时候,这种情况就要使用继承了。所以这么看来继承是对上面两种功能的一个黏合剂。

之所以会想到这些,是因为自己在写一个webservice加载库的时候得到的体会。这个库已经提供了一系列最基本的加载webservice的功 能,但是不同的程序webservice的api和类型都不是相同的,要怎么才能应用到不同程序中去呢?之前我一直想都不想直接继承了,产生一个新的 webservice加载器,然后对不同api分别进行实现。但是每次这么做的时候就发现继承的时候做了很多重复而且没有什么创造性的工作。今天才突然发 现了问题的所在,既然我的webservice库已经是一个功能基本齐备的加载器了,为什么我不简单的为这个加载器在不同的程序中创建不用的 category呢,然后在复用一些已有的api,不就能够完成工作了吗?确实,我现在通过category的方式减少了之前太多太多的重复劳动,真恨自 己为什么没有提早注意到这个问题。

关于category的另外一些见解:

  1. 虽然category可以访问类的实例变量,去不能创建新的实例变量,如果要创新的实例变量,请使用继承;
  2. 在category中,不提倡对原有方法进行重载。原因非常简单,在category中进行重载,无法对原方法进行访问,而继承中可以使用super。如果真的需要对原方法进行重载,请考虑继承,比如我要定义一个继承自UIViewController的类,就不能用Category,因为,这我定义的这个类中,我要实现UIViewController中的viewDidLoad、init等方法,用了category后父UIViewController中的这些方法将无法被调用;
  3. 一个类可以定义多个category,但是如果不同category中存在相同方法,编译器无法决定使用哪个category;
  4. 在定义category时,我们可以仅仅给出方法定义,而不需要给出具体的实现。这在程序增量开发时是非常有帮助的;
  5. category是可以被继承的。在某个父类中定义了category,那么他所有的子类都具有该category;
  6. 在需要为某个类创建私有成员方法时,也用category的方式来实现。

Category不能完全代替子类,有以下几个最大的缺点:

  1. 当在Category中覆盖一个继承的方法,在Category中的方法可以通过向super类发送一个消息来调用被继承的方法。但是,如果Category中覆盖的那个方法已经在这个类的其它Category定义过了,则之前定义的方法将没有机会被程序调用
  2. 在Category中无法确定其能够可靠的覆盖某个方法,而这个方法已经在其它的Category中定义过。这个问题在使用Cocoa框架时尤其 突出。当你想覆盖某个框架已经定义好的方法时,该方法已经在其它Category中实现,这样就无法确定哪个定义和实现会被最先使用,带来很大的不确定 性。
  3. 如果你重新覆盖定义了一些方法,往往会导致这个方法在整个框架中实现发生了变化。举例来说,如果你增加了NSObject中 windowWillClose:的实现,这会导致所有的窗口调用那个新实现的方法,从而改变所有NSWindows实例的行为。这会带来很多不确定性, 并很有可能导致程序的崩溃。

OC中protocol、category和继承的关系--转的更多相关文章

  1. oc中protocol、category和继承的区别

    OC中protocol.category和继承的区别以前还是有点迷糊,面试的时候说的有点混乱,现在结合一些资料总结一下. 利用继承,多态是一个很好的保持"对扩展开放.对更改封闭"( ...

  2. OC中分类(Category)和扩展(Extension)

    1.分类的定义 category是Objective-C 2.0之后添加的语言特性,中文也有人称之为分类.类别.Category的主要作用是为已经存在的类添加方法.这个大家可能用过很多,如自己给UIC ...

  3. 浅谈OC中的Category

    OC特有的分类Category,依赖于类.它可以在不改变原来的类内容的基础上,为类增加一些方法.分类的使用注意: (1)分类只能增加方法,不能增加成员变量: (2)在分类方法的实现中可以访问原来类中的 ...

  4. 在编译oc中protocol时出现的错误

    Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang ...

  5. OC基础--分类(category) 和 协议(protocol)

    OC 中的category分类文件相当于 C#中的部分类:OC 中的protocol协议文件(本质是头文件)相当于 C#中的接口.今天就简单说明一下OC中的这两个文件. 由于视频中的Xcode版本低, ...

  6. ios--->OC中Protocol理解及在代理模式中的使用

    OC中Protocol理解及在代理模式中的使用 Protocol基本概念 Protocol翻译过来, 叫做"协议",其作用就是用来声明一些方法: Protocol(协议)的作用 定 ...

  7. OC中的@interface和java中的区别以及 @implementation @protocol

      java 在java中的interface是‘接口’的意思,而java的类声明用class,即接口用interface声明,类是用class声明,是两个独立的部分. 只有在类声明要实现某个接口时, ...

  8. java中的继承与oc中的继承的区别

    为什么要使用继承? 继承的好处: (1)抽取出了重复的代码,使代码更加灵活 (2)建立了类和类之间的联系 继承的缺点: 耦合性太强 OC中的继承 1.OC中不允许子类和父类拥有相同名称的成员变量名:( ...

  9. .NET Framework中重点类型的继承关系

    继承关系 Object ├─Array │ └─T[] ├─ArrayList ├─List<T> └─String 集合类型的接口 下图展示了集合类型的各种接口的相互关系.注意,下图中所 ...

随机推荐

  1. js:简单的拖动效果

    效果演示:https://jsfiddle.net/dwqs/b5ywws9f/embedded/result/ html: <div class="wrap"> &l ...

  2. [React] Use the Fragment Short Syntax in Create React App 2.0

    create-react-app version 2.0 added a lot of new features. One of the new features is upgrading to Ba ...

  3. 西门子PLC学习笔记六-(Step7指令简单介绍)

    1.指令操作数 指令操作数由操作标示符和參数组成. 操作标识符由主标识符和辅标识符组成. 主标识符有:I(输入过程影像寄存器).Q(输出过程映像寄存器).M(位寄存器).PI(外部输入寄存器).PQ( ...

  4. OpenCV实践之路——Python的安装和使用

    本文由@星沉阁冰不语出品,转载请注明作者和出处. 文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/50936076 微博:http ...

  5. 李洪强iOS开发之性能优化技巧

    李洪强iOS开发之性能优化技巧 通过静态 Analyze 工具,以及运行时 Profile 工具分析性能瓶颈,并进行性能优化.结合本人在开发中遇到的问题,可以从以下几个方面进行性能优化. 一.view ...

  6. myeclipse配置hadoop开发环境

    1.安装Hadoop开发插件 hadoop安装包contrib/目录下有个插件hadoop-0.20.2-eclipse-plugin.jar,拷贝到myeclipse根目录下/dropins目录下. ...

  7. Pulse-code modulation

    脉冲编码调制(Pulse Code Modulation,PCM),由A.里弗斯于1937年提出的,这一概念为数字通信奠定了基础,60年代它开始应用于市内电话网以扩充容量,使已有音频电缆的大部分芯线的 ...

  8. FOUNDATION OF ASYNCHRONOUS PROGRAMMING

    The async and await keywords are just a compiler feature. The compiler creates code by using the Tas ...

  9. 使用linux内核hrtimer高精度定时器实现GPIO口模拟PWM,【原创】

    关键词:Android  linux hrtimer 蜂鸣器  等待队列 信号量 字符设备 平台信息:内核:linux3.4.39 系统:android/android5.1平台:S5P4418  作 ...

  10. Spring Cloud 与 Dubbo 区别

      Dubbo Spring Cloud 服务注册中心 Zookeeper Spring Cloud Netflix Eureka 服务调用方式 RPC REST API 服务监控 Dubbo-mon ...