类别(Category)与类扩展 (Extension)的区别

iOS类别(Class Category)

Category在iOS开发中使用非常的频繁,特别是在为系统类进行拓展的时候,我们可以不用继承系统类,直接给系统类添加方法,最大程度的体现了Objective-C的动态语言特性。
#import 
@interface NSObject (Category)
- (void)myMethod;
@end
这是一个最简单的Category,作用于NSObject ,给NSObject 扩展了一个myMethod方法.
Category的注意点:
  • Category的小括号内一定要有名字;故Class Extension亦被称之为匿名分类;
#import
@interface 类名(分类名字)
/* 方法声明*/
@end
@implement 类名(分类名字)
/*方法实现*/
@end
  • Category的方法不一定非要在@implement中实现,也可以在其他位置中实现,但是当调用Category的方法时,依据继承树没有找到该方法的实现,程序则会崩溃;并且,Category的方法优先级较高,可以覆盖原类的方法;
  • Category的方法中,不可以调用super方法;
  • 在实际开发中要注意的是,Category 方法可能会覆盖于同一个类class 的其它 category 中的方法。但也可能被覆盖,因为不法预知他们的加载优先顺序,出现这种情况通常会在编译时出错。如果在一个开发的SDK中使用了类别, 就最好保证类别名不同于使用者的类别名以及类别方法也不同于使用者的类别方法名, 通常通过加前缀来做到。
  • Category理论上不能添加成员变量,但是可以使用@dynamic(即运行时Runtime)来弥补这种不足.

使用Category(类别/分类)

  • 对框架提供类的扩展(没有源码,不能修改);
  • 不想生成一个新的子类的情况下,例如对NSArry的扩展;
  • 方便做项目管理,可以将一份源码在多个地方共享或者做方法版本管理、多人协作开发、用本地版本替换公共版本实现。

iOS类扩展(Class Extension)

  • 作用:
    • 能为某个类添加成员变量,属性,方法;
    • 一般的类扩展写到.m文件中;
    • 一般的私有属性写到类扩展中
#import
@interface myClass()
{
     // 成员变量
}
// 属性
// 方法
@end
@implement
@end
  • 当需要声明一个属性,它对外是只读的,但是在内部是可以修改的,这时可以通过Extension来实现;
//.h文件
@interface myClass : NSObject
@property (readOnly)NSString *name; // 该.h文件对外公开
@end

   //.m文件
@interface myClass ()
@property(readWrite)NSString *name;//该.m文件对外是不公开的.当然这里也可以放在专门的一个.h文件中,但同样不把这个文件进行公开
@end
@implement myClass()
@synthesize name;
//...
@end

Category和Extension的区别

  • Category的小括号中有名字,而Extension没有;
  • Category只能扩充方法,不能扩充成员变量和属性;
  • 如果Category声明了声明了一个属性,那么Category只会生成这个属性的set,get方法的声明,也就不是会实现.
//Category(类别,分类)
@interface myClass (Category)
// 只会生成set,get方法的声明,创建的对象没有name属性.
@property (nonatomic,copy) NSString *name;
@end

// Extension(类扩展)
@interface myClass
// 创建name成员变量,并声明和实现set,get方法
@property (nonatomic,copy) NSString *name;
@end

推荐阅读更多精彩内容