Swift中创建通用转换管道遇泛型问题,如何实现可复用?
Swift 类型擦除实现多类型转换器管道
你遇到的核心问题是带关联类型的协议无法直接作为数组元素类型:每个遵循协议的结构体(比如LowercaseTransformation和ReverseTransformation)都是独立的具体类型,而Swift数组要求所有元素必须是同一类型,因此直接将不同转换器放入数组会导致类型歧义或不兼容。
通过类型擦除技术可以解决这个问题——将不同类型的转换器包装成统一的类型,既能放进同一个数组,又能保留泛型的灵活性和可复用性。以下是完整实现:
import Foundation protocol Transformation { associatedtype Target func transform(_ input: Target) -> Target } struct LowercaseTransformation: Transformation { func transform(_ input: String) -> String { input.lowercased() } } struct ReverseTransformation: Transformation { func transform(_ input: String) -> String { String(input.reversed()) } } // 类型擦除包装器:统一所有处理同一Target类型的Transformation实例 struct AnyTransformation<Target>: Transformation { private let _transform: (Target) -> Target init<Transformer: Transformation>(_ transformer: Transformer) where Transformer.Target == Target { _transform = transformer.transform } func transform(_ input: Target) -> Target { _transform(input) } } // 修改后的Pipeline:以Target为泛型参数,接受统一类型的转换器数组 struct Pipeline<Target> { let transformations: [AnyTransformation<Target>] func run(_ input: Target) -> Target { var output = input transformations.forEach { output = $0.transform(output) } return output } } // 测试字符串转换管道 let pipeline = Pipeline(transformations: [ AnyTransformation(LowercaseTransformation()), AnyTransformation(ReverseTransformation()) ]) let input = "Hello World" let output = pipeline.run(input) print(output) // 输出:dlrow olleh
关键逻辑说明
类型擦除包装器
AnyTransformation- 它通过泛型初始化方法,接受任意遵循
Transformation协议且Target匹配的转换器实例 - 内部用闭包捕获原始转换器的
transform方法,对外隐藏具体的转换器类型,只暴露统一的接口
- 它通过泛型初始化方法,接受任意遵循
通用管道
Pipeline<Target>- 不再依赖具体的转换器类型,而是针对目标类型
Target设计 - 只要是处理同一
Target的转换器,都可以通过AnyTransformation包装后加入管道
- 不再依赖具体的转换器类型,而是针对目标类型
可复用性扩展
如果需要支持其他类型的转换(比如Int),只需新增遵循协议的转换器并包装即可:struct DoubleTransformation: Transformation { func transform(_ input: Int) -> Int { input * 2 } } struct AddOneTransformation: Transformation { func transform(_ input: Int) -> Int { input + 1 } } let intPipeline = Pipeline(transformations: [ AnyTransformation(DoubleTransformation()), AnyTransformation(AddOneTransformation()) ]) print(intPipeline.run(5)) // 输出:11
内容的提问来源于stack exchange,提问作者iCediCe
相关产品推荐
相关产品推荐

