You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

纯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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 15:54:07