分类

  在Objective-C中,除了通过新建子类的方式来向类添加新方法外,还可以通过分类的方式。分类提供了一种简单的方式,将类的定义模块化到相关方法的组或分类中,它还提供了扩展现有类定义的简便方式,并且不需要访问类的源代码,也无须创建子类。

  比如:

//SomeClass+MathOps.h
#import "SomeClass.h"
@interface SomeClass (MathOPs)
-(SomeClass *) add: (SomeClass *)s;
-(SomeClass *) sub: (SomeClass *)s;
-(SomeClass *) div: (SomeClass *)s;
-(SomeClass *) mul: (SomeClass *)s;
@end

  这里不用列出父类,也不用向编译器告知实例变量,因为从import的文件的接口部分已经这样做了。

  可以将所有的方法的定义放在一个实现部分。也就是说,可以在一个实现文件中定义SomeClass.h接口部分中的所有方法,以及MathOps分类中的所有方法。或者,在单独的实现部分定义分类的方法,这种情况下,这些方法的实现部分必须找出方法所属的分类。如@implementation SomeClass (MathOps) 这样。

  如果将分类放到一个主类定义文件中,那么这个类的所有用户都将访问这个分类中的方法。如果不能直接修改原始的头文件,则只能将分类单独保存文件。

类的扩展

  创建一个未命名的分类,且在()内不指定名字,这是一种特殊情况,这种特殊语法定义为类的扩展。定义一个像这样的未命名分类时,可以通过定义附加的实例变量来扩展类,这在命名的分类中是不允许的。未命名分类中声明的方法需要在主实现区域实现,而不是在分离的实现区域中实现。如果没有实现未命名分类的接口部分列出的全部方法,编译器会发出警告。

比如,在一个类的实现文件中:

//SomeClass.m
#import "SomeClass.h"
//类的扩展
@interface SomeClass ()
@property int pp;
-(void)someFunc;
@end //--------------------------
@implementation SomeClass
@synthesize pp;
.....
@end

  通过添加一个新的实例变量和方法扩展了这个类,并合成了存取方法。

  未命名分类是非常有用的,因为它们的方法都是私有的。如果需要写一个类,其数据和方法仅供类本身使用,未命名分类比较合适。

分类的注意事项:

  分类可以覆写该类中的另一个方法,不过这是拙劣的设计,因为覆写一个方法之后,再也不能访问原来的方法。如果需要覆写,正确的选择是创建子类,子类中覆盖父类的方法,此时仍然可以通过super来调用父类原方法。

  可以拥有许多分类,如果一个方法定义在多个分类中,该语句不会指定使用哪个分类。

  通过分类添加新方法来扩展类不仅会影响这个类,同时也会影响它的所有子类。

协议

  协议是多个类共享的一个方法列表,协议中列出的方法并没有相应的实现,计划由其他人来实现的。协议提供一种方式,用指定的名称定义一组多少有点相关的方法。这些方法有的是必须实现的(@required),有的是可选的(@optional)。

  定义协议是使用@protocol指令,后面加上协议名称。

  当采用某协议时,在@interface行最后的一对<>中列出协议名称即可,同时在实现部分至少实现协议的必须实现方法。

  比如:@interface SomeClass:SuperClass <SomeProtocol>

  协议是无类的,它不引用任何类,任何类都可以遵守某个协议。可以使用comformsToProtocol:方法检查一个对象是否遵循某协议。

代理

  协议也是一种两个类之间的接口定义。定义了协议的类可以看做是将协议定义的方法代理给了实现它们的类,这样,类的定义可以更为通用,因为具体的动作由代理类来承担,来响应某些事件或者定义某些参数。Cocoa和iOS非常依赖代理这个概念。比如UITableView类,这个类不清楚表格的标题是什么,需要包含多少区块或是包含多少行,填充表格的内容是什么。所以,代理定义了一个UITableViewDataSource协议,如果它需要信息,比如表格中每个区块有多少行,它就会调用类中实现协议的相关方法。UITableView类还定义了其他的协议如UITableViewDelegate,协议还定义了一些方法,如表格某行被选中需要怎样,UITableView不知道要做什么,所以将这个代理给了实际用户。

非正式协议

  非正式协议实际上是一个分类,列出了一组方法但是没有实现他们。每个人都继承相同的根对象,因此,非正式协议通常是为根类定义的。有时,非正式协议又被称为抽象协议。因为非正式协议本身不是协议而是分类,所以编译器不提供协议相关的帮助,不会存在遵守或者不遵守非正式协议或者由编译器测试这样的概念。

合成对象

  除了通过派生子类和分类可以扩展类定义以外,还有一项技术可以定义一个类包含其他类的一个或多个对象,这个新类的对象就是合成对象,因为它是由其他对象组成的。

  通过派生子类扩展父类,子类就集成了父类所有的实例变量和方法,一些情况下,有些方法并不适用于子类,然而子类的用户却有可能会访问它们。作为创建子类的替代方式,可以定义一个新类,它包含要扩展类的实例变量,然后,只需在新类中定义适合该类的方法。比如:

@interface NewClass:NSObject
{
SomeClass *s;
}
-(void)newFunc;
@end

  这里需要注意,与子类扩展不同,子类版本允许直接访问父类的方法,这里NewClass的对象不能直接访问SomeClass的方法了,而是在自己的方法里比如newFUnc里边,通过实例变量s来访问那些可以被用到的方法。记住,这里在初始化时,需要覆写init或者自定义初始化方法来给s分配空间。

iOS开发笔记系列-基础5(分类和协议)的更多相关文章

  1. iOS开发笔记系列-基础1(数据类型与表达式)

    学习iOS开发快两年了,去年完成MagViewer之后就因为公司的其他业务繁重,除了维护这个应用之外,只是断断续续地自己做一些实验开发,没有再发布新的应用,这里想整理一下学习过程中的笔记,以便加深印象 ...

  2. iOS开发笔记系列-基础2(类)

    面向对象编程总是离不开类和对象的,Objective-C也不例外,不过Objective-C中的类还有一些自己的独特点. 类的声明和定义 在iOS开发中,类的声明与定义通常都是分开的,类得声明通常存放 ...

  3. iOS开发笔记系列-基础6(预处理程序)

    预处理程序提供了一些工具,使用这些工具更易于开发.阅读.修改程序,也易于将程序移植到不同的系统中.又称为宏. #define #define语句的基本用途之一就是给富豪名称指定程序常量.比如: #de ...

  4. iOS开发笔记系列-基础3(多态、动态类型和动态绑定)

    多态:相同的名称,不同的类 使不同的类共享相同方法名称的能力成为多态.它让你可以开发一组类,这组类中的每一个类都能响应相同的方法名.每个类的定义都封装了响应特定方法所需要的代码,这使得它独立于其他的类 ...

  5. iOS开发笔记系列-基础7(C语言特性)

    Objective-C是C语言的扩展,因此,也具备很多C语言的基本特性,这里只罗列部分. 块(Blocks) 块是对C语言的一种扩展,它并未作为标准ANSI C所定义的部分,而是Apple添加到语言中 ...

  6. iOS开发笔记系列-基础4(变量与数据类型)

    对象的初始化 对象的初始化方法一般都如下: -(id)init { self=[super init]; if(self){ ... } return self; } 这个方法首先会调用父类的初始化方 ...

  7. IOS科研IOS开发笔记学习基础知识

    这篇文章是我的IOS学习笔记,他们是知识的基础,在这里,根据记录的查询后的条款. 1,UIScrollView能完毕滚动的功能. 示比例如以下: UIScrollView *tableScrollVi ...

  8. Winform开发框架之客户关系管理系统(CRM)的开发总结系列3-客户分类和配置管理实现

    我在本系列随笔的开始,介绍了CRM系统一个重要的客户分类的展示界面,其中包含了从字典中加载分类.从已有数据中加载分类.以及分组列表中加载分类等方式的实现,以及可以动态对这些节点进行配置,实现客户分类的 ...

  9. iOS开发技巧系列---详解KVC(我告诉你KVC的一切)

    KVC(Key-value coding)键值编码,单看这个名字可能不太好理解.其实翻译一下就很简单了,就是指iOS的开发中,可以允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值.而不需 ...

随机推荐

  1. jquery插件——日历控件

    今天在网上有看到一个jquery插件——日历控件,不过之前也在柯乐义的网站上看到了(http://keleyi.com/ 推荐下) 这个插件看着比较大气,所以干脆也分享下,以后自己也好用一点儿 1.页 ...

  2. ch03-文字版面的设计

    Ch03: 文字版面的编辑 3.1 版面控制标记 3.1.1 取消文字换行: <NOBR> 1-取消换行文字实例:1-取消换行文字实例; 1-取消换行文字实例; 2-取消换行文字实例:2- ...

  3. leveldb源码笔记

    关于KV数据库leveldb的介绍,网上已经太多了,这里只是自己再学习源码过程中,整理的笔记,磁盘存储和内存存储的结构用了伪代码表示出来了,首先是内存中存储结构,然后是log文件存储结构和磁盘数据ss ...

  4. Dapper.net 在Parameterized时对于String的扩展(转)

    虽然Dapper通过提供的DbString本身支持对于String的指定Parameterized,但这方法明显不够,当Insert时,我们更希望是把一个Poco直接传递过去,而不是来new一个匿名函 ...

  5. Delphi TRichEdit加载word内容

    procedure TForm1.btn6Click(Sender: TObject);var WordApp: Variant; //声明一个word对象beginWordApp := Create ...

  6. Backbone.js developer 武汉 年薪8w-10w

    1.   精通Backbone.js 2.   熟练Ajax.NoSQL.RESTful APIs 3.   了解Pusher.com和 Parse.com 4.   具有良好的沟通能力,学习能力,敬 ...

  7. Python学习之eventlet.greenpool

    该模块提供对 greenthread 池的支持. greenthread 池提供了一定数量的备用 greenthread ,有效限制了孵化 greenthread 过多导致的内存不足,当池子中没有足够 ...

  8. 多校7 HDU5818 Joint Stacks

    多校7 HDU5818 Joint Stacks 题意:n次操作.模拟栈的操作,合并的以后,每个栈里的元素以入栈顺序排列 思路:开三个栈,并且用到了merge函数 O(n)的复杂度 #include ...

  9. java集合框架复习

    数组类Array是java中最基本的一个存储结构,它用于存储 一组连续的对象或一组类型相同的基本类型的数据. Array特点:效率高,但容量固定且无法动态改变, 缺点:无法判断其中存有多少元素,len ...

  10. Intellij IDEA使用Maven构建Scala项目

    1.安装IDEA的Scala插件       使用自带的在线安装方式较为简单.File--Setting--Plugins--Browse reposities   2.创建项目     File - ...