[学习笔记—Objective-C]《Objective-C-基础教程 第2版》第十二章 种类

[学习笔记—Objective-C]《Objective-C-基础教程 第2版》第十二章 类别

12.1 创建类别

类别(category)是一种为现有的类添加新方法的方式

例:获取字符串的长度并存入NSDictionary字典中

  • 不使用类别的方式:
      NSNumber *number;
      number = [NSNumber numberWithUnsignedInt: [string length]];
      // ... do something with number
  • 使用类别的方式:

    • 类别的声明:
@interface NSString (NumberConvenience)

- (NSNumber *) lengthAsNumber; 

@end // NumberConvenience

注意

  1. 括号内写入类别的名称,添加给NSString的
  2. 类别不能添加实例变量,所以没有实例变量的声明部分
  3. 可以添加属性,但属性必须是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 类别的缺陷:

  1. 无法向类中添加新的实例变量
  2. 名称冲突,类别的方法名与现有的方法重名时,类别具有更高的优先级(利用前缀避免)

12.12 类别的优势:

  1. 将类的实现代码分散到多个不同文件或框架中
  2. 创建对私有方法对向前引用
  3. 向对象添加非正式协议(informal protocol)

12.2 类扩展(class extension)

类扩展:一种特殊的类别,不需要名字。

特点:

  1. 不需要名字
  2. 可以在你自己的类中使用它
  3. 可以添加实例变量
  4. 可以将只读权限改成可读写的权限
  5. 创建数量不限

例:建立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)

注意:

  1. 类别可以访问其继承的类的实例变量
  2. 不仅可以将一个类的实现代码分散到多个不同的源文件中,还可以分散多个不同的框架中

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");

}

版权声明:本文为博主原创文章,未经博主允许不得转载。