Swift中泛型约束能否支持枚举?如何减少重复代码?
解决Swift中泛型协议与重复代码的问题
问题根源分析
你之前的泛型方案无法运行的核心问题是:struct Grunt<T: Foo>中的约束T: Foo不合法——Foo是枚举类型而非协议,Swift枚举不支持继承,因此不能将泛型参数约束为枚举类型。此外,带关联类型的协议Fum不能直接作为函数参数类型(除非使用any Fum,需Swift 5.7+)。
重构方案
1. 给嵌套枚举添加统一协议约束
定义一个空协议,让Foo.Bar和Foo.Baz共同遵守,以此作为泛型参数的约束:
protocol FooNested {} enum Foo { enum Bar: FooNested { case prop11, prop12, prop13 // 其他case } enum Baz: FooNested { case prop21, prop22, prop23 // 其他case } }
2. 重构泛型协议与结构体
修正Fum协议和Grunt结构体,确保泛型参数约束合法,同时保留自动补全能力:
protocol Fum { associatedtype Thud: FooNested var zot: Thud { get set } } struct Grunt<T: FooNested>: Fum { var zot: T // 显式初始化器,确保创建实例时的自动补全正常工作 init(zot: T) { self.zot = zot } }
此时创建实例可以正常触发自动补全:
let grunt1 = Grunt(zot: Foo.Bar.prop11) // 自动补全Foo.Bar的所有case let grunt2 = Grunt(zot: Foo.Baz.prop23) // 自动补全Foo.Baz的所有case
3. 统一定义协议方法
针对Bletch协议,有两种可行的实现方式:
方式一:泛型方法(兼容所有Swift版本)
通过泛型方法接收任意遵守Fum协议的类型,避免重复定义:
protocol Bletch { func doSomething<T: Fum>(to grunt: T) } // 示例实现 struct BletchImpl: Bletch { func doSomething<T: Fum>(to grunt: T) { // 通用逻辑处理 print("处理实例,zot值为:\(grunt.zot)") // 如果需要针对具体枚举类型做特殊处理,可通过类型转换实现 if let barZot = grunt.zot as? Foo.Bar { print("这是Foo.Bar类型:\(barZot)") } else if let bazZot = grunt.zot as? Foo.Baz { print("这是Foo.Baz类型:\(bazZot)") } } }
方式二:使用any Fum(Swift 5.7及以上)
如果不需要在方法中访问zot的具体类型,仅做统一抽象处理,可以使用any Fum作为参数类型:
protocol Bletch { func doSomething(to grunt: any Fum) } struct BletchImpl: Bletch { func doSomething(to grunt: any Fum) { print("处理通用Fum实例") } }
进阶优化:让嵌套枚举实现共同行为
如果doSomething的逻辑需要依赖zot的具体行为,可在FooNested协议中定义统一方法,让枚举各自实现,避免类型转换:
protocol FooNested { func performAction() } enum Foo { enum Bar: FooNested { case prop11, prop12, prop13 func performAction() { print("执行Foo.Bar的操作:\(self)") } } enum Baz: FooNested { case prop21, prop22, prop23 func performAction() { print("执行Foo.Baz的操作:\(self)") } } } // 此时doSomething可以简化为: func doSomething<T: Fum>(to grunt: T) { grunt.zot.performAction() }
内容的提问来源于stack exchange,提问作者Tiny Tim
相关产品推荐
相关产品推荐

