一.category(类别)
类别是一种类扩展的机制,能为现有的类添加新方法。
①类别的基本语法
@interface部分,如:
@interface NSString (NumberConvenience)
- (NSNumber *) lengthAsNumber;
@end
我们为NSString类添加了名为NumberConvenience的类别。
注:
- 类别只可以添加方法,不可以添加实例变量
- 类别可以添加属性,但属性必须是@dynamic类型的
@implementation部分
@implementation NSString (NumberConvenience)
-(NSNumber *) lengthAsNumber{
…...
}
②类别的优点
- 将类的实现代码分散到多个不同的文件和框架中,这样可以是类划分成多个模块,降低类的复杂度,便于维护。
- 类别的扩展功能,已经存在的类可以在不更改的情况下通过类别进行功能扩展。
- 类别可以实现功能的局部化封装,模拟实现私有方法。
- 通过类别向对象添加非正式协议。这样任何类的对象都可以作为委托对象来使用,它可以列出对象能够执行的所有方法。
③类别的缺点
- 类别不可以添加实例变量
- 类别会发生名称冲突,即类别中的方法与现有方法重名,类别具有更高的优先级。
二.protocol(协议)
类似于C++中的纯虚函数,协议只是声明,没有实现,在遵从此协议的类中实现
①协议的基本语法
- 声明协议
如:
@protocol NSCopying
- (id) copyWithZone: (NSZone *) zone;
@end
- 采用协议
在类的@interface声明中列出协议的名称,如:
@interface Car : NSObject <NSCopying>{
…...
}
@end //Car
- @required和@optional属性(Objective-C 2.0的新特性)
@required属性要求遵从此协议的方法必须实现这种方法,@optional属性则不强制要求,可以通过respondsToSelector:@select( )判断
②注意事项
- 正式协议要求显示的采用
- 协议名称必须唯一
- 采用协议意味着你承诺实现该协议@required属性的所有方法。否则,编译器会生成警告来提醒。
- 协议可以继承父协议
如:
@protocol MySuperDuberProtocol <MyParentProtocol>
③协议的意义
- protocol可以将业务方法定义剥离出来,形成单独的文件,对于不关心的功能可以不关注他的具体实现,这样有利于分工
三.delegate(委托/代理)
委托就是某个对象指定另一个对象处理某些特定任务的设计模式
如:我们让A对象去实现一项工作,不过B对象自己不完成这项工作,它有一个代理A对象,A对象会完成此项工作。如下所示:
//A.h
@interface A :NSObject
-(void)Log;
@end
//A.m
@implementation A
-(void)Log{
NSLog(@"This is A Log");
}
@end
//B.h
@interface B :NSObject{
A* delegate;
}
@property (nonatomic, retain)A* delegate;
-(void)callLog;
@end
//B.m
@implementation B
@synthesize delegate;
-(id)init{
if (self = [super init] ) {
delegate = [[A alloc]init];
}
returnself;
}
-(void)callLog{
NSLog(@"This is B callLog");
[self.delegate Log];
}
@end
四.相关题目
①Objective-C的类可以实现多重继承吗?可以实现多接口吗?
Objective-C不可以直接使用多继承,cocoa中的所有类都是NSObject的子类,要实现多继承要使用protocol委托代理来实现。可以实现多接口,通过多接口可以实现C++中的多重继承。
②继承和类别在实现中有何区别?
- 类别可以在不改变原来代码的情况下往里面添加新的方法,但继承不可以。
- 类别只能添加方法,不能删除修改方法,但继承即可以增加,也可以修改或者删除方法。
- 类别不可以增加属性,而继承可以。
③类别和匿名类别(类扩展/extension)的区别
- 类别中只能增加方法
- 类扩展不仅可以增加方法,还可以增加实例变量,只是该 实例变量默认是@private类型 的(作用范围只能在自身类,而不是子类或其他地方);
- 类扩展中声明的方法没被实现,编译器会报警,但是类别中的方法没被实现编译器是不会有任何警告的。这是因为类扩展是在编译阶段被添加到类中,而类别是在运行时添加到类中。
- 类扩展是在 .m 文件中声明私有方法的非常好的方式。
- 类扩展所声明的方法必须依托对应类的实现部分来实现(即不能像类别那样拥有独立的实现部分(@implementation部分))
- 类扩展只能本类调用方法,子类也无法调用父类的延展。
④delegate和protocol的结合使用
protocol是一种协议,定义需实现什么样的公共接口,delegate则是被委托的对象需要实现什么接口,而两则结合的话则可以理解为被委托的对象需要实现protocol所要求的公共接口。如:
- (id <NSNetServiceBrowserDelegate>)delegate;
要求被委托的对象需要实现协议NSNetServiceBrowserDelegate所要求的接口,只需要遵守所需的协议,就可以设置任意的对象为委托。
⑤谈谈在实际开发项目中对delegate、protocol、category的应用
protocol&delegate:
在平时工作中,常常出现需要开发一个app,但app本身并不关心业务部分的内容,比如:有一种交易模式是由app端驱动终端进行交易(我们称app端为上位机),具体的交易的数据采集数据打包由终端负责,而上位机负责和服务器的通讯及UI的显示,也就是上位机并不需要关心终端的具体交易实现,此时便使用protocol定制一套接口,app只需要调用,具体实现在终端部分实现。但同时,上位机上送数据给服务器的接口由终端进行调用,此时便可以使用delegate实现委托,由上位机实现此接口。
category:
例如:公司内部封装的一个底层库中,其中有一个头文件定义了一个用于存储蓝牙信息的类,这些信息都是只读属性。现在需要调用此类,同时想重写其中一些信息,并添加一些初始化蓝牙设备的接口,此时便可以在不定义新的类同时不改变原有类的基础上使用category进行类的扩展,以达到需求。
⑥回调函数的实现
- 通过block实现
- 通过protocol实现
- 通过delegate实现
- 结合protocol和delegate实现