iOS开发笔记系列-基础5(分类和协议)

分类

  在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分配空间。

时间: 2024-08-04 18:23:50

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

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

多态:相同的名称,不同的类 使不同的类共享相同方法名称的能力成为多态.它让你可以开发一组类,这组类中的每一个类都能响应相同的方法名.每个类的定义都封装了响应特定方法所需要的代码,这使得它独立于其他的类定义.这是因为Objective-C的运行时系统在执行方法时知道消息的接收者是哪个类的对象,它总是携带有关“一个对象属于哪个类”这样的信息,该信息能使系统在运行时做出决定,而不是在编译时. 动态绑定和id类型 id数据类型是一种通用的对象类型,可以用来存储属于任何类的对象.当使用id类型的时候,程序

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

Objective-C是C语言的扩展,因此,也具备很多C语言的基本特性,这里只罗列部分. 块(Blocks) 块是对C语言的一种扩展,它并未作为标准ANSI C所定义的部分,而是Apple添加到语言中的.它看起来很像函数,可以给它传递参数,它也具有返回值,与函数不同的是,块定义在函数或方法内部,并能够访问在函数或者方法范围内块之外的任何变量.一般来说,它可以访问到这些变量但是不能修改它们的值,有一个特殊的块修改器(由块前面含有两个下划线的字符组成)能够修改块内变量的值.块本身也能够作为参数传递给

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

这篇文章是我的IOS学习笔记,他们是知识的基础,在这里,根据记录的查询后的条款. 1,UIScrollView能完毕滚动的功能. 示比例如以下: UIScrollView *tableScrollView; tableScrollView=[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];//窗体大小 tableScrollView.contentSize=CGSizeMake(640, 480);//设置内容视图的大

PHP开发笔记系列(一)-PDO使用

之前一段时间,开始了php的研究,看了关于PDO的一些资料,发现不错,整理和总结一下,作为开发笔记,留待日后使用,<PHP开发笔记系列(一)-PDO使用>. PDO是PHP Data Objects的简称,是一种数据库访问抽象层.PDO是用于多种数据库的一致接口.类比的说,PDO做的事情类似于JAVA中的持久层框架(Hibernate.OpenJPA)的功能,为异构数据库提供一个统一的编程接口,这样就不必再使用mysql_*.pg_*这样的函数,也不必再写自己的"GenericDAO

iOS开发UINavigation系列二——UINavigationItem

iOS开发UINavigation系列二--UINavigationItem 一.引言 UINavigationItem是导航栏上用于管理导航项的类,在上一篇博客中,我们知道导航栏是通过push与pop的堆栈操作来对item进行管理的,同样,每一个Item自身也有许多属性可供我们进行自定制.这篇博客,主要讨论UINavigationItem的使用方法. UINavigationBar:http://my.oschina.net/u/2340880/blog/527706. 二.来说说UINavi

IOS开发笔记-百度地图(第三方库)

最近做了百度地图,在导入SDK后遇到了一些问题 编译错误: linker command failed with exit code 1 (use -v to see invocation) 想了很多办法,查了很多资料,最后终于解决. 可能原因: 1. 有重复的.m文件,或者未导入 解决办法:有重复的删除即可 在工作左边导航栏Target-->Build Phases-->compile Sources中,第三库库的所有.m文件都添加到里面 2.Valid Architectures 的值 在

iOS开发UINavigation系列三——工具栏UIToolBar

iOS开发UINavigation系列三--工具栏UIToolBar iOS中除了UINavinationBar之外,还有工具栏UIToolBar可以供我们使用,工具栏和导航栏十分类似,只是功能更加简单,工具栏中也有UIBarButtonItem按钮,在前两篇博客中,对导航栏和导航项都进行的讨论,地址如下: UINavigationBar:http://my.oschina.net/u/2340880/blog/527706 UINavigationItem:http://my.oschina.

iOS开发UINavigation系列一——导航栏UINavigtionBar

iOS开发UINavigation系列一--导航栏UINavigtionBar 一.导航栏的使用 在iOS开发中,我们通常会使用导航控制器,导航控制器中封装了一个UINavigationBar,实际上,我们也可以在不使用导航控制器的前提下,单独使用导航栏,在UINavigationBar中,也有许多我们可以定制的属性,用起来十分方便. 二.UINavigationBar的创建和风格类型 导航栏继承于UIView,所以我们可以像创建普通视图那样创建导航栏,比如我们创建一个高度为80的导航栏,将其放

ios开发笔记----exc_bad_access(code=1, address=0x789870)野指针错误,假死debug状态

错误原因: exc_bad_access(code=1, address=0x789870)野指针错误,主要的原因是,当某个对象被完全释放,也就是retainCount,引用计数为0后.再去通过该对象去调用其它的方法就会出现野指针错误. 例如: Person *jerry = [[Person alloc]init];  //  retainCount引用计数为1 [jerry eat];  //  调用吃的方法 [jerry release];  //  释放jerry这个对象到 retain