纯Scala无第三方依赖实现case class的None值属性与默认值合并
首先注意:你提供的代码样例中ProductAttributes的locationId属性存在拼写不一致问题(类定义时写为localtionId,默认实例赋值时写为locationId),请先修正拼写避免编译错误。
方案1:内置合并方法(属性少的场景最优)
直接在case class中定义合并方法,通过Option#orElse实现优先级逻辑:当前实例属性为None时才取默认值对应属性。
case class ProductAttributes( price: Option[Int], locationId: Option[Int], colorCount: Option[Int] ) { def mergeWithDefault(default: ProductAttributes): ProductAttributes = ProductAttributes( price = price.orElse(default.price), locationId = locationId.orElse(default.locationId), colorCount = colorCount.orElse(default.colorCount) ) } // 使用示例 val defaultProduct = ProductAttributes(price = None, locationId = Some(1), colorCount = Some(1)) val customAttrs = ProductAttributes(price = Some(99), locationId = None, colorCount = Some(2)) val merged = customAttrs.mergeWithDefault(defaultProduct) // 合并结果:ProductAttributes(Some(99), Some(1), Some(2))
方案2:扩展方法实现(不修改原类定义)
如果不能改动原有ProductAttributes的代码,可以用扩展方法实现合并逻辑:
Scala 2 写法
implicit class ProductAttributesOps(attrs: ProductAttributes) { def mergeWithDefault(default: ProductAttributes): ProductAttributes = ProductAttributes( price = attrs.price.orElse(default.price), locationId = attrs.locationId.orElse(default.locationId), colorCount = attrs.colorCount.orElse(default.colorCount) ) }
Scala 3 写法
extension (attrs: ProductAttributes) def mergeWithDefault(default: ProductAttributes): ProductAttributes = ProductAttributes( price = attrs.price.orElse(default.price), locationId = attrs.locationId.orElse(default.locationId), colorCount = attrs.colorCount.orElse(default.colorCount) )
使用方式和方案1完全一致。
方案3:通用合并工具(多case class场景适用)
如果你有大量带Option属性的case class都需要做默认值合并,Scala 3可以用原生的类型派生能力实现通用工具,无需为每个类单独写合并逻辑,完全不依赖第三方库:
import scala.deriving.Mirror import scala.compiletime.* def mergeDefaults[T <: Product](custom: T, default: T)(using m: Mirror.ProductOf[T]): T = val mergedElements = custom.productIterator.zip(default.productIterator).map { case (customVal: Option[_], defaultVal: Option[_]) => customVal.orElse(defaultVal) case (customVal, _) => customVal // 非Option属性直接保留自定义值 }.toArray m.fromProduct(Tuple.fromArray(mergedElements))
使用示例:
val merged = mergeDefaults(customAttrs, defaultProduct)
内容的提问来源于stack exchange,提问作者Blankman
相关产品推荐
相关产品推荐

