Objective-C 分类(Category) vs 扩展(Extension)

119 阅读2分钟

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)增加私有属性、方法(需要类的源码)。

这两者各有用途,合理使用可以提高 代码组织性和封装性!🚀