类别(category)
- 类别:类别是一种为现有的类添加新方法的方式。使用类别你可以为任何类添加新的方法,包括那些没有源代码的类。
- 通常会以“类名称+类别名称”的风格命名。这并不是硬性的规定,但却是一个好习惯。例如:NSString+NumberAsNSNumber.
类别的声明
#import <Foundation/Foundation.h>@interface NSString (NumberConvenience)
-(NSNumber *) lenthAsNumber;
@end
声明部分有几个非常有趣的特点。
- 类的名称后面是位于括号中的新名称,这意味着类别的名称叫做NumberConvenience,而且它是添加给NSString类的。只要保证类别名称唯一,你可以向一个类中添加任意数量的类别。
- 你可以指定想要添加类别的类(上述是NSString)和类别的名称(上述是NumberConvenience),还可以列出你要添加的方法,最后以@end结束。由于不能添加新的实例变量,因此这是不会像类声明那样包含实例变量声明的部分。
- 你可以在类别中添加属性,但是不能添加实例变量,而且属性必须是@dynami类型的。
类别的实现
#import "NSString+NumberConvenience.h"
@implementation NSString (NumberConvenience)
-(NSNumber *) lenthAsNumber
{
//获取客串的长度值
NSUInteger length =[self length];
return ([NSNumber numberWithUnsignedInt:length]);
}
@end
类别的实现与声明部分相似。
main函数的实现
#import <Foundation/Foundation.h>#import "NSString+NumberConvenience.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSMutableDictionary *dict =[NSMutableDictionary dictionary];
[dict setObject:[@"hello" lenthAsNumber] forKey:@"hello"];
[dict setObject:[@"once time" lenthAsNumber] forKey:@"once time"];
NSLog(@"%@",dict);
}
return 0;
}
通过以上步骤我们完成了让程序接收一系列的字符串,然后确定每个字符串的长度并存入到字典中。
这是有几点需要说明
- @"字符串"这种形式的字符串实际上就是地地道道的NSString对象,它们对消息的响应正如任何其他NSString对象一样。
- 任何NSString对象都能响应lengthAsNumber消息,包括字面量字符串、可变字符串、其他工具集某部分字符串、文件中加载的字符串、从因特网海量内容中撮的字符串,等等。
类扩展
类扩展的特点
- 它不需要名字
- 你可以在包含你的源代码的类(也就是你自己的类)中使用它。
- 你可以添加实例变量。
- 你可以将只读权限改成可读写的权限。
- 创建的数量不限
#import <Foundation/Foundation.h>@interface Things : NSObject
@property (assign) NSInteger thing1;
@property (readonly,assign) NSInteger thing2;
-(void)resetAllValues;
@end
#import "Things.h"
@interface Things ()
{
NSInteger thing4;
}
@property (readwrite,assign) NSInteger thing2;
@property (assign) NSInteger thing3;
@end
这里没有继承的类,我们所做的基本上就是获取Things类,并通过私有属性和方法来扩展它。在这里我们修改了thing2读写权限,我们还添加了私有属性thing3,它只可以在这个类内部使用,另外还添加了thing4这个实例变量,它同样是私有的。
类别的优势与缺陷
优点:
- 将类的实现代码分散到多个不同的文件或框架中。
- 创建对私有方法的前向引用。
- 向对象添加非正式协议。
缺陷:
- 类别无法向类中添加新的实例变量。类别没有空间容纳实例变量。
- 名称冲突,也就是类别中的方法与现有的方法重名。当发生名称冲突时,类别具有更高的优先级。你的类别方法将完全取代初始方法,导致初始方法不再可用。
类别和继承
- 为现有的类添加新的行为,通常也可以采用创建子类的方法(继承),
但是类别是有限制的,如现有的类你没有源代码,或者现有的类是类簇的形式存在。都无法添加新的行为。