Swift中结构体遵循协议报错及多类型实现协议的适配问题
问题核心原因
你遗漏的核心要点是:Swift中协议类型(存在类型)和遵守该协议的具体类型是两种完全不同的类型,不会自动隐式转换匹配协议要求。
你最初的写法中,FooProtocol要求的getBar类型是BarProtocol(即any BarProtocol,存在类型),而foo结构体的getBar是具体类型foo.bar,尽管foo.bar遵守BarProtocol,但二者类型不匹配,因此编译报错。
你后续把FooProtocol的getBar类型写死为foo.bar,直接限制了所有遵守FooProtocol的类型必须使用foo.bar作为getBar的类型,自然其他自定义实现会触发相同的协议遵守错误。
解决方案
使用带关联类型的协议即可满足多类型遵守的需求,既保留getBar必须遵守BarProtocol的约束,又支持不同实现使用不同的具体Bar类型。
第一步:修改协议定义
protocol BarProtocol { var getBar: String { get } } protocol FooProtocol { var getFoo: String { get } // 声明关联类型,约束必须遵守BarProtocol associatedtype BarType: BarProtocol var getBar: BarType { get } }
第二步:原有代码无需额外修改即可通过编译
Swift会自动根据结构体的属性类型推断关联类型的具体值:
struct foo { var getFoo: String var getBar: bar struct bar { var getBar: String } } extension foo.bar: BarProtocol {} // 不再报错,自动推断BarType = foo.bar extension foo: FooProtocol {}
第三步:自定义其他遵守FooProtocol的类型
可以按需选择使用固定具体类型,或者支持任意BarProtocol实现:
// 实现1:使用固定的自定义Bar类型 struct CustomBar: BarProtocol { var getBar: String } struct CustomFoo: FooProtocol { var getFoo: String var getBar: CustomBar // 自动推断BarType = CustomBar } // 实现2:支持存储任意遵守BarProtocol的实例 struct FlexibleFoo: FooProtocol { typealias BarType = any BarProtocol // 显式指定关联类型为存在类型 var getFoo: String var getBar: any BarProtocol }
补充说明
如果你需要将FooProtocol作为变量/参数的类型使用,Swift 5.7及以上版本需要使用any FooProtocol(存在类型,可存任意遵守该协议的实例)或者some FooProtocol(不透明类型,固定为某一个遵守该协议的类型)修饰。
内容的提问来源于stack exchange,提问作者CaptainStiggz
相关产品推荐
相关产品推荐

