Objective-C 分类(Category) vs 扩展(Extension)
1. 分类(Category)
特点
- ✅ 可以为已有类添加方法(不能添加实例变量)。
- ✅ 可以作用于系统类和自定义类。
- ✅ 方法在运行时动态加载,可能会覆盖原方法(方法替换)。
- ✅ 通常用于代码模块化、拆分实现文件。
- ✅ 只能添加方法,不能添加属性(除非使用关联对象)。
语法
// Category 头文件
@interface NSString (MyCategory)
- (void)sayHello;
@end
// Category 实现文件
@implementation NSString (MyCategory)
- (void)sayHello {
NSLog(@"Hello from Category!");
}
@end
使用
NSString *str = @"Objective-C";
[str sayHello]; // 输出: Hello from Category!
2. 扩展(Class Extension)
特点
- ✅ 只能作用于本类(不能扩展系统类)。
- ✅ 可以声明私有方法和属性(支持实例变量)。
- ✅ 只能在
@implementation之前定义,并且必须有源代码(否则编译报错)。 - ✅ 通常用于声明私有方法或私有属性,提高封装性。
- ✅ 不支持动态加载,方法必须在编译时实现。
语法
// 在.m文件中(只能本类用)
@interface MyClass ()
@property (nonatomic, strong) NSString *privateProperty;
- (void)privateMethod;
@end
@implementation MyClass
- (void)privateMethod {
NSLog(@"This is a private method.");
}
@end
使用
MyClass *obj = [[MyClass alloc] init];
// obj.privateMethod(); // ❌ 编译错误,外部不可见
3. 分类 vs 扩展:核心区别
| 对比项 | 分类(Category) | 扩展(Extension) |
|---|---|---|
| 作用范围 | 任何类(包括系统类) | 仅限本类 |
| 能否添加实例变量 | ❌ 不能(除非用关联对象) | ✅ 可以 |
| 能否添加方法 | ✅ 可以 | ✅ 可以(通常用于私有方法) |
| 是否需要类的源码 | ❌ 不需要 | ✅ 需要 |
| 编译时 vs 运行时 | 运行时动态加载 | 编译时静态编译 |
| 用途 | 扩展已有类的方法 | 定义私有属性、方法 |
4. 什么时候用哪种?
- ✅ 如果想要给已有类(包括系统类)添加方法 👉 使用分类(Category)
- ✅ 如果想在类的实现文件中定义私有属性或方法 👉 使用扩展(Extension)
- ✅ 如果需要添加实例变量 👉 只能用扩展(Extension),因为分类不支持(不使用关联对象)。
总结
- 分类(Category) → 扩展已有类的功能(不能增加实例变量)。
- 扩展(Extension) → 增加私有属性、方法(需要类的源码)。
这两者各有用途,合理使用可以提高 代码组织性和封装性!🚀