Objective-C 和 Swift 中的 Protocol(协议)

Objective-C 和 Swift 中的 Protocol(协议) 都用于定义一组方法、属性或行为的“契约”,但它们在语法、能力、运行时机制和使用方式上存在显著差异。以下是两者的详细对比:


一、基础概念

特性 Objective-C Protocol Swift Protocol
定义方式 @protocol ... @end protocol ... { }
实现方式 类通过 <ProtocolName> 声明遵循 类/结构体/枚举通过 : ProtocolName 遵循
是否支持可选方法 ✅(需配合 @optional ❌(默认必须实现),但可通过 @objc + optional 模拟(仅限类)
是否支持扩展(Extension) ✅(可通过 extension 提供默认实现)
是否支持泛型约束 ✅(如 where T: Equatable
是否支持关联类型(Associated Types) ✅(associatedtype

二、语法对比

1. 定义协议

Objective-C:

@protocol MyProtocol <NSObject> // 可继承其他协议
- (void)requiredMethod;
@optional
- (void)optionalMethod;
@end

Swift:

protocol MyProtocol: AnyObject { // 可限制为类类型
    func requiredMethod()
    var someProperty: Int { get set }
}

⚠️ Swift 协议不能直接定义可选方法,除非标记为 @objc 并继承自 NSObjectProtocol


2. 遵循协议

Objective-C:

@interface MyClass : NSObject <MyProtocol>
@end

@implementation MyClass
- (void)requiredMethod { /* 必须实现 */ }
// optionalMethod 可不实现
@end

Swift:

class MyClass: MyProtocol {
    func requiredMethod() { }
    var someProperty: Int = 0
}
// 若未实现 requiredMethod → 编译错误

三、关键区别详解

1. 可选方法(Optional Requirements)

  • Objective-C

    • 原生支持 @optional
    • 调用前需用 respondsToSelector: 判断。
  • Swift

    • 默认所有方法必须实现。
    • 若需可选方法,必须:
      @objc protocol MyProtocol {
          @objc optional func optionalMethod()
      }
      
    • 限制:
      • 协议必须标记 @objc(意味着只能被 遵循,不能被 struct/enum 遵循)。
      • 方法必须兼容 Objective-C(不能有泛型、元组、Swift 特有类型等)。

2. 默认实现(Default Implementation)

  • Objective-C:❌ 不支持。

    • 通常通过 Category基类 提供共用逻辑。
  • Swift:✅ 通过 Protocol Extension 提供默认实现:

    extension MyProtocol {
        func defaultMethod() {
            print("Default implementation")
        }
    }
    
    • 遵循者可选择是否重写。
    • 这是 面向协议编程(POP) 的核心特性。

3. 类型系统与泛型支持

  • Objective-C

    • 协议是运行时概念,无泛型。
    • 无法表达“某个类型必须符合多个协议”的复杂约束。
  • Swift

    • 协议是一等公民,支持:
      • 协议组合func foo(x: A & B & C)
      • 泛型约束
        func process<T: MyProtocol & Codable>(item: T)
        
      • 关联类型(Associated Types)
        protocol Container {
            associatedtype Item
            var count: Int { get }
            mutating func append(_ item: Item)
        }
        

4. 值类型支持

  • Objective-C:协议只能被 类(Class) 遵循(因为基于 runtime 的消息机制)。

  • Swift:协议可被 类、结构体、枚举 遵循。

    struct Point: MyProtocol { ... }
    enum State: MyProtocol { ... }
    

    → 支持更安全、高效的值语义编程。


5. 协议作为类型(Existential Types)

  • Swift 允许将协议作为类型使用(称为 Existential):

    let items: [MyProtocol] = [obj1, obj2]
    func handle(thing: MyProtocol) { ... }
    
    • 但若协议含 Selfassociatedtype,则不能直接作为类型(需用泛型或 some / any 关键字,Swift 5.7+)。
  • Objective-C:协议可作为类型(id<MyProtocol>),但功能有限。


6. 运行时 vs 编译时

  • Objective-C

    • 协议检查主要在 运行时(通过 conformsToProtocol:)。
    • 更灵活,但也更容易出错(如未实现 required 方法导致 crash)。
  • Swift

    • 协议一致性在 编译时 强制检查(除非使用 @objc optional)。
    • 更安全,性能更好(尤其对值类型)。

四、互操作性(Interop)

  • Swift 协议若标记 @objc,可被 Objective-C 使用。
  • Objective-C 协议在 Swift 中自动桥接为 Swift 协议。
  • 但 Swift 特性(如关联类型、泛型约束)在 Objective-C 中不可见。

五、总结对比表

特性 Objective-C Protocol Swift Protocol
可选方法 ✅ 原生支持 ⚠️ 仅限 @objc 类型
默认实现 ✅(通过 extension)
值类型支持 ✅(struct/enum)
泛型 & 关联类型
协议组合 有限(id<A, B> ✅(A & B
编译时安全 ❌(运行时检查)
面向协议编程(POP) 强(核心范式之一)
性能 消息派发(较慢) 静态/虚表派发(更快)

六、使用建议

  • 纯 Swift 项目:优先使用 Swift 协议,利用 POP、默认实现、值类型等优势。
  • 混合项目(ObjC + Swift)
    • 若需被 ObjC 调用,协议需加 @objc
    • 避免在跨语言协议中使用 Swift 特有特性。
  • 需要可选方法:考虑是否真的需要;否则用默认实现 + 协议扩展更安全。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容