12.1 创建类别
类别(category)是一种为现有的类添加新方法的方式
例:获取字符串的长度并存入NSDictionary字典中
- 不使用类别的方式:
NSNumber *number;
number = [NSNumber numberWithUnsignedInt: [string length]];
// ... do something with number
- 使用类别的方式:
- 类别的声明:
@interface NSString (NumberConvenience)
- (NSNumber *) lengthAsNumber;
@end // NumberConvenience
注意:
- 括号内写入类别的名称,添加给NSString的
- 类别不能添加实例变量,所以没有实例变量的声明部分
- 可以添加属性,但属性必须是
dynamic
类型的,添加属性的好处是可以通过点表达式访问setter和getter方法- 类别的实现:
- (NSNumber *) lengthAsNumber{
unsigned int length = [self length];
return ([NSNumber numberWithUnsignedInt: length]);
//向字符串发送lengthAsNumber,返回该字符串的长度的NSNumber对象
} // lengthAsNumber
测试文件:
NSMutableDictionary *dict;
dict = [NSMutableDictionary dictionary];
[dict setObject: [@"hello" lengthAsNumber]
forKey: @"hello"];
[dict setObject: [@"iLikeFish" lengthAsNumber]
forKey: @"iLikeFish"];
[dict setObject: [@"Once upon a time" lengthAsNumber]
forKey: @"Once upon a time"];
NSLog (@"%@", dict); //输出:“键=键内容”
优点:只要输入一个字符串,向该字符串发送lengthAsNumber,立即能返回该字符串的长度的NSNumber对象
注意:
此类别属于NSString,因此任何NSString对象都能响应lengthAsNumber消息
12.11 类别的缺陷:
- 无法向类中添加新的实例变量
- 名称冲突,类别的方法名与现有的方法重名时,类别具有更高的优先级(利用前缀避免)
12.12 类别的优势:
- 将类的实现代码分散到多个不同文件或框架中
- 创建对私有方法对向前引用
- 向对象添加非正式协议(informal protocol)
12.2 类扩展(class extension)
类扩展:一种特殊的类别,不需要名字。
特点:
- 不需要名字
- 可以在你自己的类中使用它
- 可以添加实例变量
- 可以将只读权限改成可读写的权限
- 创建数量不限
例:建立Things类的扩展
- 原Things类:
@interface Things : NSObject
@property (assign) NSInteger thing1;
@property (readonly, assign) NSInteger thign2;
- 扩展Things类:
//获取Things类,并通过添加私有属性和方法扩展它
@interface Things()
{
NSInteger thing4;//私有的
}
@property (readwrite, assign) NSInteger thing2;//改变了读写权限,只能在这个类中访问的私有方法,在公共的接口只有getter方法
@property (assign) NSInteger thign3;//私有的
注意:
面向对象编程的一个特征就是信息隐藏,只需要把用户需要的展示出来,其他的不需要。我们可以把这个类别放在.m文件中,也可以放在私有的头文件中。
12.3 利用类别分散实现代码
如果想将大型(有很多方法)的类分散到多个不同的.m文件中,可以使用类别。
NSWindow类有数百个方法,但使用分类:
@interface NSWindow(NSKeyboardUI) //键盘
@interface NSWindow(NSToolbarSupport) //工具栏
@interface NSWindow(NSDrag) //拖放功能
@interface NSWindow(NSCarbonExtensions)
注意:
- 类别可以访问其继承的类的实例变量
- 不仅可以将一个类的实现代码分散到多个不同的源文件中,还可以分散多个不同的框架中
Cocoa的设计人员通过类别使数据功能放在Foundation框架中,而绘图共呢个放在Appkit框架中。
12.4 通过类别创建向前引用(Forward References)
如果在不方便将方法声明的前提下调用方法,或者正在使用的是另一个类中尚未发布的方法,那么就需要类别。
具体做法:
Car类的公共接口里声明rotateTires
的方法,在类别中声明move
TireFromPosition:toPosition:的方法来实现rotateTires
的方法,rotateTires方法可以使用它。
@intreface Car(Private)
-(void)moveTireFromPosition:(int) pos1 toPosition: (int) pos2;
@end // Private
注意:放入各自的@implementation文件中
12.5 非正式协议和委托类别
非正式协议是NSObject的一个类别,列出了对象可以响应的方法。非正式协议用于实现委托
委托(delegate)是一种对象,由另一个类请求执行某些工作。委托是一种允许你轻松定制对下岗行为的技术。
例:
当用户点击某行时,tableView对象准备执行之前,它会询问其委托对象是否能选择此行。
12.51 ITUnesFinder 项目 (略)
//新的NSNetServiceBrowser对象:
NSNetServiceBrowser *browser;
browser = [[NSNetServiceBrowser alloc] init];
//新的ITunesFinder对象
ITunesFinder *finder;
finder = [[ITunesFinder alloc] init];
//告诉 net browser将 ITunesFinder 对象作为代理
[browser setDelegate: finder];
//告诉浏览器搜索iTunes共享
[browser searchForServicesOfType: @"_daap._tcp"
inDomain: @"local."];
12.52 委托和类别
委托是类别的另一种应用,一个NSObject的类别可以被发送给委托对象
@interface NSObject (NSNetServiceBrowserDelegateMethods)
- (void) netServiceBrowserWillSearch:
(NSNetServiceBrowser *) browser;
- (void) netServiceBrowserDidStopSearch:
(NSNetServiceBrowser *) browser;
- (void) netServiceBrowser:
(NSNetServiceBrowser *) browser
didRemoveService: (NSNetService *) service
moreComing: (BOOL) moreComing;
@end
通过声明为NSObject的类别,NSNetServiceBrowser可以给任何对象(作为代理的对象)发送其中一条消息-为非正式协议
注意:对于非正式协议,你只声明你想声明的即可。
12.53 响应选择器
选择器(selector):只是一个方法名称
指定选择器:@selector()
;
Car类的setEngine:
方法的选择器:@selector(setEngine:)
Car类的setTire:atIndex:
方法的选器:@selector(setTire:atIndex:)
询问对象其是否能响应某个特定的消息
Car *car = [[Car alloc] init];
if([Car respondsToSelector: @selector(setEngine:)])
{
NSLog(@"Yes");
}
版权声明:本文为博主原创文章,未经博主允许不得转载。