Swift新手求教:为NSDecimalNumber实现带可选值的自定义运算符
实现NSDecimalNumber的可选值自定义运算符
嘿,作为Swift新手能想到给NSDecimalNumber自定义可选值运算符,这点真的很棒!我来给你一步步拆解怎么实现~
核心思路:处理可选值的安全解包
对于可选值的运算符重载,核心就是先安全解包左右操作数——如果其中任意一个是nil,我们可以选择返回nil(最符合Swift可选语义的常用场景),或者给nil设置默认值(比如当成0计算)。下面分别展示两种场景的实现:
场景1:只要有一个值为nil,结果返回nil
这是最贴合Swift可选值设计逻辑的实现,和Optional链式调用的行为一致。你可以直接在NSDecimalNumber的扩展里添加以下代码,还能复用你已经写好的非可选版本代码:
extension NSDecimalNumber { // 保留你已实现的非可选版本运算符 static func + (left: NSDecimalNumber, right: NSDecimalNumber) -> NSDecimalNumber { return left.adding(right) } static func - (left: NSDecimalNumber, right: NSDecimalNumber) -> NSDecimalNumber { return left.subtracting(right) } static func * (left: NSDecimalNumber, right: NSDecimalNumber) -> NSDecimalNumber { return left.multiplying(by: right) } static func / (left: NSDecimalNumber, right: NSDecimalNumber) -> NSDecimalNumber { return left.dividing(by: right) } // 可选值版本运算符 static func + (left: NSDecimalNumber?, right: NSDecimalNumber?) -> NSDecimalNumber? { guard let left = left, let right = right else { return nil } // 直接复用非可选版本,避免重复代码 return left + right } static func - (left: NSDecimalNumber?, right: NSDecimalNumber?) -> NSDecimalNumber? { guard let left = left, let right = right else { return nil } return left - right } static func * (left: NSDecimalNumber?, right: NSDecimalNumber?) -> NSDecimalNumber? { guard let left = left, let right = right else { return nil } return left * right } static func / (left: NSDecimalNumber?, right: NSDecimalNumber?) -> NSDecimalNumber? { guard let left = left, let right = right else { return nil } // 额外处理除数为0的情况,避免崩溃 guard right != NSDecimalNumber.zero else { print("警告:除数不能为0") return nil } return left / right } }
额外优化:支持混合运算(可选+非可选)
如果需要支持“可选值和非可选值混合运算”的场景(比如左边是NSDecimalNumber?,右边是NSDecimalNumber),可以再重载一组运算符,让代码更简洁:
extension NSDecimalNumber { // 左可选,右非可选的加法 static func + (left: NSDecimalNumber?, right: NSDecimalNumber) -> NSDecimalNumber? { guard let left = left else { return nil } return left + right } // 左非可选,右可选的加法 static func + (left: NSDecimalNumber, right: NSDecimalNumber?) -> NSDecimalNumber? { guard let right = right else { return nil } return left + right } // 减法、乘法、除法同理,复制上面的模式即可 static func - (left: NSDecimalNumber?, right: NSDecimalNumber) -> NSDecimalNumber? { guard let left = left else { return nil } return left - right } static func - (left: NSDecimalNumber, right: NSDecimalNumber?) -> NSDecimalNumber? { guard let right = right else { return nil } return left - right } }
场景2:将nil视为默认值(比如0),返回非可选结果
如果你的业务逻辑需要把nil当成0来计算,直接返回非可选的NSDecimalNumber,可以这样写:
extension NSDecimalNumber { static func + (left: NSDecimalNumber?, right: NSDecimalNumber?) -> NSDecimalNumber { let leftVal = left ?? NSDecimalNumber.zero let rightVal = right ?? NSDecimalNumber.zero return leftVal + rightVal } // 减法、乘法、除法同理,替换对应的运算符和方法即可 }
这样即使其中一个值是nil,运算也能正常进行,返回一个确定的结果。
内容的提问来源于stack exchange,提问作者Eddie
相关产品推荐
相关产品推荐

