Swift泛型优化:统一处理FloatingPoint与Complex<T>的isApproximatelyEqual
优雅实现FloatingPoint与Complex的近似相等判断
1. 用协议抽象近似相等行为
定义协议统一近似相等的方法签名,确保与AlgebraicField的关联类型对齐:
protocol ApproximatelyEquatable { associatedtype Magnitude: Comparable & FloatingPoint func isApproximatelyEqual(to other: Self, tolerance: Magnitude) -> Bool }
2. 给浮点类型添加默认实现
扩展FloatingPoint协议,使所有浮点类型自动具备近似相等判断能力:
extension FloatingPoint where Magnitude: FloatingPoint { func isApproximatelyEqual(to other: Self, tolerance: Magnitude) -> Bool { abs(self - other) <= tolerance } } extension FloatingPoint: ApproximatelyEquatable where Magnitude: FloatingPoint {}
3. 给复数类型实现近似相等判断
先确保Complex<T>遵守AlgebraicField(若尚未实现),再扩展实现近似相等逻辑(分别校验实部和虚部):
// 让Complex<T>适配AlgebraicField协议 extension Complex: AlgebraicField where T: AlgebraicField { typealias Magnitude = T.Magnitude // 实现AlgebraicField要求的代数运算(如加减乘除等) } // 扩展Complex<T>实现ApproximatelyEquatable extension Complex: ApproximatelyEquatable where T: ApproximatelyEquatable { func isApproximatelyEqual(to other: Complex, tolerance: T.Magnitude) -> Bool { real.isApproximatelyEqual(to: other.real, tolerance: tolerance) && imaginary.isApproximatelyEqual(to: other.imaginary, tolerance: tolerance) } }
4. 上层泛型函数的调用方式
如果原有泛型函数约束为T: AlgebraicField,只需追加ApproximatelyEquatable约束,即可直接调用方法,无需类型判断或强制转换:
func processValues<T: AlgebraicField & ApproximatelyEquatable>(_ a: T, _ b: T) -> Bool { return a.isApproximatelyEqual(to: b, tolerance: 1e-6) }
若无法修改原有泛型函数的约束,可通过AlgebraicField的条件扩展实现隐式适配:
extension AlgebraicField where Self: ApproximatelyEquatable { func isApproximatelyEqual(to other: Self, tolerance: Magnitude) -> Bool { return self.isApproximatelyEqual(to: other, tolerance: tolerance) } }
这种方案利用Swift的协议扩展和类型推断能力,让编译器自动匹配对应类型的实现,彻底摆脱枚举类型判断和强制转换的冗余代码,同时保证类型安全。
内容的提问来源于stack exchange,提问作者Joseph Levy
相关产品推荐
相关产品推荐

