Objective-C类别(类的扩展)
原文链接 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方法,该方法询问对象以确定其是否能够响应某个特定的消息。