OOP继承与POP对比:iOS视图控制器IBOutlet及方法复用选型问题
场景选型与实现方案解答
1. 当前场景是否继承比协议更合适?
是,这个场景下继承是性价比更高的选择。
你们的两个ViewController完全符合is-a的继承适用条件:SecondViewController的UI组件(IBOutlet)、presenter依赖、基础业务逻辑完全是FirstViewController的超集,没有需要裁剪父类能力的场景。使用继承可以直接复用父类所有存储属性(包括IBOutlet、presenter实例)和成员方法,不需要重复声明任何公共代码,代码量最少,维护成本最低。
业界提倡优先使用POP是为了避免继承带来的强耦合、单继承限制等问题,不是要求所有场景硬套POP,匹配业务场景的方案才是最优的。
2. 选择协议方案如何避免重复代码?
你之前的协议方案问题在于Swift的协议本身不能定义存储属性,只能定义属性约束,所以IBOutlet这类存储属性无法直接在协议层复用,公共方法可以通过协议默认实现复用,完整实现步骤如下:
步骤1:抽取公共能力协议
声明公共的属性约束和方法要求,限定协议仅能被类遵守:
protocol CommonVCProtocol: AnyObject { // 公共IBOutlet约束 var firstButton: UIButton! { get set } var secondButton: UIButton! { get set } // 公共presenter约束 var presenter: CommonPresenterProtocol! { get set } // 公共业务方法要求 func firstFunction() func secondFunction() }
步骤2:添加协议默认实现
给协议添加扩展,约束实现者为UIViewController类型,就可以在默认实现里直接访问UIKit能力和协议声明的公共属性:
extension CommonVCProtocol where Self: UIViewController { func firstFunction() { // 公共逻辑直接写在这里,可直接调用firstButton、presenter等属性 firstButton.isSelected = true presenter.loadCommonData() } func secondFunction() { // 公共逻辑实现 } }
步骤3:抽取新增功能的独立协议
protocol AdditionalVCProtocol: AnyObject { var additionalButton: UIButton! { get set } func additionalFunction() } extension AdditionalVCProtocol where Self: UIViewController { func additionalFunction() { // 新增逻辑实现 } }
步骤4:两个ViewController分别遵守协议
注意:存储属性(IBOutlet、presenter)还是需要在各自的类中单独声明,这是Swift语法的限制,无法通过协议规避
class FirstViewController: UIViewController, CommonVCProtocol { // 仍需单独声明公共IBOutlet @IBOutlet weak var firstButton: UIButton! @IBOutlet weak var secondButton: UIButton! var presenter: CommonPresenterProtocol! // 公共方法已经有默认实现,无需重复编写 } class SecondViewController: UIViewController, CommonVCProtocol, AdditionalVCProtocol { // 仍需单独声明公共IBOutlet @IBOutlet weak var firstButton: UIButton! @IBOutlet weak var secondButton: UIButton! var presenter: CommonPresenterProtocol! // 新增IBOutlet @IBOutlet weak var additionalButton: UIButton! // 公共方法和新增方法都有默认实现,无需重复编写 }
3. 是否需要使用协议默认实现?
如果选择POP方案,必须用协议默认实现,否则两个ViewController都要重复编写所有公共业务方法,协议默认实现就是用来解决方法复用的核心手段。但存储属性的重复声明是Swift POP当前无法解决的问题。
最终选型建议
- 如果后续两个ViewController不会出现功能分化(比如不需要裁剪FirstViewController的能力给SecondViewController用),直接选继承,代码更简洁。
- 如果后续两个VC要分别叠加不同的横向能力(比如一个要支持分享、一个要支持草稿保存),或者会出现功能分化,选POP,灵活度更高,不会被单继承的继承树限制。
内容的提问来源于stack exchange,提问作者jackbob
相关产品推荐
相关产品推荐

