Objective-C类别(类的扩展)

2014-04-25 Xiaosong Gao 更多博文 » 博客 » GitHub »

iOS Mac

原文链接 https://gaoxiaosong.github.io/2014/04/25/objective-c-category.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。


说明

  • 类别名可以随便取。
  • 类别是一个类,它是添加了新功能的现有类。
  • 使用类别就是为了能够为现有类添加新的方法,不用继承该现有类,就可使用现有类的对象调用添加的方法了。
  • 类别可以使类的实现分散在多个文件中。
  • 类别中不能有变量,类别中没有放变量的位置。
  • 如果类中的方法和类别中的方法名称相同,这将造成冲突,类别的方法将完全取代类的方法。
  • 同一个类的不同类别声明了相同的方法,这将导致不稳定,哪个方法会被调用是不确定的。
  • 不建议在类别中覆盖类中的方法,因为在类别中的方法不能调用superClass的方法(因为没有元数据支持)。
  • 类别方法不能覆盖于同一个类的其它类别中的方法。因为无法预知他们的加载优先顺序,就可能在编译时出错。
  • 对类库的类别方法覆盖对导致整个类库的行为发生变化,因此调用那些方法的类不知道方法的实现已经发生了变化。

警告

  • 虽然类别不限于任何类,但是仍然不建议编写针对rootClass的类别。原因是影响面较大,其它开发人员如果不注意的话就会出问题。
  • 而且类对象也可能调用这些方法,甚至在调用时的self指针不是实例而是类对象本身。

声明类别

@interface NSString (NumberConvenience)
- (NSNumber *)lengthAsNumber;
@end

实现类别

@implementation NSString (NumberConvenience)
- (NSNumber *)lengthAsNumber
{
  unsigned int length = [self length];
  return ([NSNumber numberWithUnsignedInt:length]);
}
@end

在实现部分也包括类名、类别名和新方法的实现代码。

类别的局限性

  • 无法向类中添加新的实例变量,类别没有位置容纳实例变量。无法添加实例变量的局限可以使用字典对象解决。
  • 名称冲突,即当类别中的方法与原始类方法名称冲突时,类别具有更高的优先级。类别方法将完全取代初始方法从而无法再使用初始方法。

委托

创建一个NSObject的类别称为"创建一个非正式协议",因为可以作为任何类的委托对象使用。

响应选择器

选择器只是一个方法名称,但它以Objective-C运行时使用特殊方式编码,以快速执行查询可以使用@selector()预编译指定选择器,其中方法名位于圆括号中。

NSObject提供了一个名为respondsToSelector方法,该方法询问对象以确定其是否能够响应某个特定的消息。