如何用另一协议实现带关联类型的协议?遇合规错误求可行方案
这种实现方式确实不可行,核心原因是Swift的关联类型要求绑定具体类型,而any AnotherProtocol属于存在类型(existential type),无法满足关联类型的约束。
问题根源
BaseProtocol中的关联类型T明确要求遵循Identifiable<String>的具体类型,但any AnotherProtocol只是一种"类型占位符",用来表示任意遵循AnotherProtocol的类型,它本身并不是一个可以被关联类型绑定的具体类型。所以不管是直接把array声明为[any AnotherProtocol],还是给T指定any AnotherProtocol,都会触发"不符合协议"的错误。
可行的解决方案
方案1:将MyStruct改为泛型结构体
让MyStruct的泛型参数遵循AnotherProtocol,以此满足BaseProtocol的关联类型要求:
protocol BaseProtocol { associatedtype T: Identifiable<String> var array: [T] { get set } } protocol AnotherProtocol: Identifiable<String> { var id: String { get set } } struct MyStruct<T: AnotherProtocol>: BaseProtocol { var array: [T] }
这种方式保留了类型安全性,数组内的元素都是同一种具体类型,适合需要严格类型约束的场景。
方案2:修改BaseProtocol,移除关联类型
如果不需要严格的类型绑定,可以直接把BaseProtocol中的数组类型改为存在类型:
protocol BaseProtocol { var array: [any Identifiable<String>] { get set } } protocol AnotherProtocol: Identifiable<String> { var id: String { get set } } struct MyStruct: BaseProtocol { var array: [any AnotherProtocol] }
由于AnotherProtocol遵循Identifiable[any AnotherProtocol]可以向上兼容[any Identifiable<String>],这样MyStruct就能正常实现协议。
方案3:使用类型擦除包装存在类型
如果不想修改原有的BaseProtocol,可以创建一个具体的包装类型,用来容纳任意遵循AnotherProtocol的实例:
protocol BaseProtocol { associatedtype T: Identifiable<String> var array: [T] { get set } } protocol AnotherProtocol: Identifiable<String> { var id: String { get set } } // 类型擦除的具体类型 struct AnyIdentifiableString: Identifiable<String> { let id: String private let base: any AnotherProtocol init(_ base: any AnotherProtocol) { self.base = base self.id = base.id } } struct MyStruct: BaseProtocol { typealias T = AnyIdentifiableString var array: [AnyIdentifiableString] // 便利初始化,方便传入any AnotherProtocol数组 init(array: [any AnotherProtocol]) { self.array = array.map(AnyIdentifiableString.init) } }
这种方式用具体类型满足了关联类型的要求,同时可以灵活处理不同的AnotherProtocol实现类。
内容的提问来源于stack exchange,提问作者Tyler

