进行 iOS 开发时,总有一个容易让人困惑的地方。
那就是 Objective-C 类别与 Swift extension 的区别。
两者都可以为已有类添加功能,因此很容易被认为是同一个概念。
先说结论:它们的外观相似,但适用对象和工作方式有很大不同。
类别只能用于类,并在运行时生效;而 extension 还可用于结构体、枚举和协议,并在编译时确定。
今天我们从实践角度逐一比较这两者。
什么是 Objective-C 类别?
类别是一种无需继承已有类即可添加方法的语法。
例如,即使没有源代码,也可以向 NSString 这类框架类添加自己的方法。
不需要源代码。
// NSString 添加电子邮件验证方法
@interface NSString (Validation)
- (BOOL)isValidEmail;
@end
关键在于,方法会在运行时附加到类上。
这带来了灵活性,但如果两个类别定义了同一个方法,也会存在无法保证哪一个优先的风险。
类别之间出现名称冲突时,很容易引发难以查明原因的 bug。
Swift extension 有什么不同?
把 Swift 的 extension 理解为类别的扩展版会更容易。
除了方法,还可以添加计算属性、初始化器、嵌套类型以及协议遵循。
更重要的是,它并不局限于类。
结构体(struct)、枚举(enum)和协议也都可以使用。
// String 添加计算属性
extension String {
var isValidEmail: Bool {
contains("@") && contains(".")
}
}
尤其是通过协议 extension 提供默认实现,这是 Objective-C 类别所不具备的强大功能。
它能大幅减少重复代码。
类别 vs extension:核心区别一览
为了方便容易混淆的读者,我整理成了表格。(以 2026 年语法为准)
| 分类 | Objective-C 类别 | Swift extension |
|---|---|---|
| 适用对象 | 仅限类 | 类、结构体、枚举和协议 |
| 计算属性 | 无法直接添加 | 可以 |
| 存储属性 | 不可以 | 不可以 |
| 协议默认实现 | 不可以 | 可以 |
| 方法名称冲突 | 存在运行时风险 | 在编译阶段阻止 |
| 生效时机 | 运行时 | 编译时 |
两者也有一个共同点。
两者都不能添加存储属性(stored property)。
如果确实需要附加状态,就必须使用 Objective-C 的 associated object 机制,但这并不算推荐做法。
实践中应该在什么时候使用哪一个?
下面分享一下我在项目中总结出的判断标准。
- 如果是纯 Swift 项目,我会毫不犹豫地使用 extension。
- 如果要维护旧的 Objective-C 代码,我会继续使用类别。
- 如果需要把通用功能提供给多个类型,协议 extension 通常是最接近正确答案的选择。
也有很多同时使用两者的情况。
因为通过 Objective-C 类别创建的功能可以直接在 Swift 中使用。
反过来也请记住,Swift extension 如果不添加 @objc,在 Objective-C 端是不可见的。
如果忽略这一点,桥接过程中很容易出现编译错误。
总之,类别是仅适用于类的运行时扩展,而 extension 是涵盖几乎所有类型的编译时扩展。
只要充分理解两者的特性,代码结构就会整洁得多。
祝你今天也享受愉快的开发时光!

