Swift泛型:将BaseVMP转换为子协议,优化ViewModel变量冗余问题
用Swift泛型消除ViewModel变量冗余的解决方案
你现在遇到的问题是基类和子类分别维护不同类型的ViewModel变量,导致冗余且容易出错。通过将BaseVC改为泛型类,我们可以让基类直接持有子类需要的具体ViewModel协议类型,同时保留基类对BaseVMP的通用处理能力,彻底消除冗余变量。
重构步骤
1. 将BaseVC改为泛型类
把BaseVC定义为泛型,并约束泛型类型必须遵循BaseVMP协议。这样基类的vm属性就能直接对应子类需要的具体子协议类型:
protocol BaseVMP { } protocol VM1P: BaseVMP { // 可添加VM1专属的方法/属性 func vm1Method() } protocol VM2P: BaseVMP { // 可添加VM2专属的方法/属性 func vm2Method() } class BaseVM: BaseVMP { } class VM1: BaseVM, VM1P { func vm1Method() { print("执行VM1专属方法") } } class VM2: BaseVM, VM2P { func vm2Method() { print("执行VM2专属方法") } } // 重构后的泛型BaseVC class BaseVC<VMType: BaseVMP> { var vm: VMType // 初始化方法,传入对应的ViewModel实例 init(vm: VMType) { self.vm = vm } // 基类处理BaseVMP的通用逻辑 func baseCommonLogic() { // 操作vm(类型为BaseVMP) print("执行基类通用逻辑") } }
2. 子类VC直接继承泛型BaseVC并指定类型
子类不需要再额外声明vm变量,只需要在继承时指定对应的ViewModel子协议类型,就能直接使用类型安全的vm属性:
class VC1: BaseVC<VM1P> { func handleVC1Business() { // 直接调用VM1P专属方法,无需类型转换 vm.vm1Method() // 调用基类通用逻辑 baseCommonLogic() } } class VC2: BaseVC<VM2P> { func handleVC2Business() { vm.vm2Method() baseCommonLogic() } }
3. 实例化VC和VM
实例化时直接传入对应的ViewModel实例,类型会自动匹配:
// 创建VM1实例并初始化VC1 let vm1 = VM1() let vc1 = VC1(vm: vm1) vc1.handleVC1Business() // 创建VM2实例并初始化VC2 let vm2 = VM2() let vc2 = VC2(vm: vm2) vc2.handleVC2Business()
额外优化:支持默认ViewModel
如果希望基类可以直接使用默认的BaseVM,可以给泛型类型添加默认值:
class BaseVC<VMType: BaseVMP = BaseVM> { var vm: VMType init(vm: VMType = VMType()) { self.vm = vm } // ... 通用逻辑 } // 不需要自定义VM的子类可直接继承 class SimpleVC: BaseVC { func doSimpleOperation() { // vm默认是BaseVM类型 print("使用默认BaseVM执行操作") } }
方案优势
- 消除冗余变量:基类和子类共用同一个
vm属性,基类层面可将其当作BaseVMP处理通用逻辑,子类层面则直接使用具体子协议类型,无需额外声明。 - 类型安全:避免了强制类型转换的运行时风险,所有类型检查都在编译阶段完成。
- 扩展性强:后续新增ViewModel协议和VC子类时,仅需指定对应泛型类型即可,无需修改基类逻辑。
内容的提问来源于stack exchange,提问作者A_G
相关产品推荐
相关产品推荐

