Swift 与 Objective-C

Objective-C 类别与 Swift extension 的区别(概念与注意事项总结)

进行 iOS 开发时,总有一个容易让人困惑的地方。

3 分钟阅读
Objective-C 类别与 Swift extension 的区别(概念与注意事项总结) 封面图

进行 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 机制,但这并不算推荐做法。


实践中应该在什么时候使用哪一个?

下面分享一下我在项目中总结出的判断标准。

  1. 如果是纯 Swift 项目,我会毫不犹豫地使用 extension。
  2. 如果要维护旧的 Objective-C 代码,我会继续使用类别。
  3. 如果需要把通用功能提供给多个类型,协议 extension 通常是最接近正确答案的选择。
如果是纯 Swift 项目,我会毫不犹豫地使用 extension。
如果是纯 Swift 项目,我会毫不犹豫地使用 extension。

也有很多同时使用两者的情况。

因为通过 Objective-C 类别创建的功能可以直接在 Swift 中使用。

反过来也请记住,Swift extension 如果不添加 @objc,在 Objective-C 端是不可见的。

如果忽略这一点,桥接过程中很容易出现编译错误。


总之,类别是仅适用于类的运行时扩展,而 extension 是涵盖几乎所有类型的编译时扩展。

只要充分理解两者的特性,代码结构就会整洁得多。

祝你今天也享受愉快的开发时光!

延伸阅读