类别:
在面向对象编程中,我们经常希望为对象添加新的行为或是方法来满足新的功能需求。实现这个目的,可以使用继承机制就可以实现,即为现有的类派生个子类,在子类中添加新的行为即可。
但是有时创建子类不是很方便,例如为类NSString添加新的行为方法,它只是一个类簇的表现形式。例如当使用stringWithFormat:类方法创建字符串时,创建的新子类无法返回。
解决办法来了,我们知道Objective-c是动态运行分配机制语言,利用这点就可以为类添加新的方法行为了。这些新的方法行为在这里叫做为“类别”。
注意:
类别的命名习惯为“类名+类别名”格式
========================================
创建类别
具体参看下面的实例代码:
声明部分:
#import <Foundation/Foundation.h>
@interface NSString (NumberConvenience)
- (NSNumber *) lengthAsNumber;
@end // NumberConvenience
实现部分:
#import "NSString+NumberConvenience.h"
@implementation NSString (NumberConvenience)
- (NSNumber *) lengthAsNumber
{
NSUInteger length = [self length];
return ([NSNumber numberWithUnsignedInteger:length]);
}
@end // NumberConvenience
正如上面所示,类别的声明和实现类似类的声明和实现,关键字相同,具体的格式规则:类名字(类别名字)。
注意:
一个类可以拥有若干个类别,为其添加新的行为方法。
=========================================
类别的缺点
当前类别有两个缺点,一个是不能向类中添加实例变量,因为类别没有空间容纳实例变量的存在;另一个就是当类别中的行为方法与类中的初始方法重名冲突时,类别中行为方法全权取代类中的同名方法。
规范:
类别中定义的行为方法,需要添加前缀来尽量与类中方法保持不同。
注意:
例如,我们使用全局字典存放对象与想要关联变量间的映射。但这样做,需要先评估下使用类别是否为最佳方式。
类别的优点
在Cocoa中,类别主要有3个用途:
1、将类的实现代码分散到多个不同文件或框架中
2、创建对私有方法的前向引用
3、向对象添加非正式协议
======================================================
类别分散实现代码
我们知道可以将类的接口放在头文件中,而类的实现放入到.m文件,但是却不能将@implements分散到不同的.m文件中,这时就可以使用类别来处理了。
下面具体新建一个项目demo来分散实现代码到多个不同的.m文件中,具体如下:
类的声明:
#import <Foundation/Foundation.h>
@interface CategoryThing : NSObject
{
NSInteger *thing1;
NSInteger *thing2;
NSInteger *thing3;
}
@end // CategoryThing
@interface CategoryThing(thing1)
- (void) setThing1 : (NSInteger) thing1;
- (NSInteger *) thing1;
@end // CategoryThing(thing1)
@interface CategoryThing(thing2)
- (void) setThing2 : (NSInteger) thing2;
- (NSInteger *) thing2;
@end // CategoryThing(thing2)
@interface CategoryThing(thing3)
- (void) setThing3 : (NSInteger) thing3;
- (NSInteger *) thing3;
@end // CategoryThing(thing3)
类的实现:
#import "CategoryThing.h"
@implementation CategoryThing
- (NSString *) description
{
NSString *desc;
desc = [NSString stringWithFormat : @"%d %d %d",thing1,thing2,thing3];
return (desc);
}
@end // description
类别的声明:
#import "CategoryThing.h"
@interface CategoryThing (Thing1)
@end
#import "CategoryThing.h"
@interface CategoryThing (Thing2)
@end
#import "CategoryThing.h"
@interface CategoryThing (Thing3)
@end
类别的实现:
#import "CategoryThing+Thing1.h"
@implementation CategoryThing (Thing1)
- (void) setThing1:(NSInteger)t1
{
thing1 = t1;
}
- (NSInteger *) thing1
{
return (thing1);
}
@end // CategoryThing
#import "CategoryThing+Thing2.h"
@implementation CategoryThing (Thing2)
- (void) setThing2:(NSInteger)t2
{
thing2 = t2;
}
- (NSInteger *) thing2
{
return (thing2);
}@end
#import "CategoryThing+Thing3.h"
@implementation CategoryThing (Thing3)
- (void) setThing3:(NSInteger)t3
{
thing3 = t3;
}
- (NSInteger *) thing3
{
return (thing3);
}@end
如上面的代码示例所示,我们使用类别将类CategoryThing的实现代码迁移到多个不同的.m文件中,在main函数中运行:
#import <Foundation/Foundation.h>
#import "CategoryThing.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
CategoryThing *ct = [[CategoryThing alloc] init];
[ct setThing1 : 3];
[ct setThing2 : 6];
[ct setThing3 : 9];
NSLog(@"results:%@",ct);
}
return 0;
}
注意:
因为使用了ARC机制,所以这里不需要自己处理对象的内存管理问题,这样使用ARC机制,将内存的管理交给编译器管理很方便。
==============================================
类别创建前向引用
在Cocoa中没有真正的私有方法,如果对象支持某个方法的名称,但是在该对象所在的类中并没有该方法的声明,这样使用这个方法的时候编译器就会发出警告,找不到该方法(该方法并不支持),所以这个问题就要解决,解决的办法就是使用类别来动态的添加对象没有的行为方法即可。
正如上面的代码中的setter和getter方法,在对象中是没有声明的,但是却在类别中声明并实现,这样编译器就不会报警告了。
====================================================
非正式协议和委托类别
Cocoa中的类会经常使用一种名为“委托(delegate)”的技术,委托是一个对象,由另一个对象负责执行请求某些工作。
最常见的情况是,编写委托对象并且将其提供给其他某些函数使用,通常是Cocoa框架中的对象,通过实现特定的方法,你可以控制Cocoa中对象行为。
好了,类别的使用就暂时总结到这里。
/**
* 技术交流群:179914858
*/