代码之家  ›  专栏  ›  技术社区  ›  Blankman

如果值为“无”,则合并案例类

  •  0
  • Blankman  · 技术社区  · 4 年前

    我有一个case类,它的属性是可选的:

    case class ProductAttributes(price: Option[Int], localtionId: Option[Int], colorCount: Option[Int])
    

    我还有一个case类,它具有每个用户都应该设置的默认值:

    val defaultProduct= ProductAttributes(locationId = Some(1), colorCount = Some(1))
    

    现在我要应用 defaultProduct 任何值 ProductAttributes 实例,并且如果该实例具有 None 对于中的任何值 默认产品 ,我希望将值设置为 默认产品

    在纯Scala中有没有一种简洁的方法可以做到这一点?(无外部LIB)

    0 回复  |  直到 4 年前
        1
  •  3
  •   Matthias Berndt    4 年前

    正如其他地方指出的,您可以简单地使用 Option orElse 方法:

    val default: ProductAttributes = ???
    
    def applyDefaults(pa: ProductAttributes): ProductAttributes =
      ProductAttributes(
        price = pa.price.orElse(default.price),
        locationId = pa.locationId.orElse(default.locationId),
        colorCount = pa.colorCount.orElse(default.colorCount)
      )
    

    但问题是:这真的是一个有用的函数吗?因为一旦调用了它,您可能希望以某种方式利用所有值现在都已定义的事实。但是怎么做呢?你可以打电话 .get 在那些上面 选项 s、 但是如果你忘了打电话,你的程序就会崩溃 applyDefaults 。或者您可以使用“安全”方法,如 getOrElse(xxx) ,那么你打算在那里放什么而不是 xxx ? 不管你放在那里,它都是死代码,因为你已经应用了默认值。

    这里的问题是,函数签名并不能表示函数的功能:它会使可选性消失。纠正这种情况的一种方法是将类型参数添加到 ProductAttributes 它告诉您这些值是否为可选值:

    case class ProductAttributes[F[_]](
      price: F[Int],
      localtionId: F[Int],
      colorCount: F[Int])
    
    type Id[A] = A
    val default = ProductAttributes[Id](20, 17, 3)
    
    def applyDefaults(pa: ProductAttributes[Option]): ProductAttributes[Id] =
      ProductAttributes[Id](
        price = pa.price.getOrElse(default.price),
        locationId = pa.locationId.getOrElse(default.locationId),
        colorCount = pa.colorCount.getOrElse(default.colorCount)
      )
    

    签名现在告诉读者函数的作用:它需要 ProductAttributes产品属性 并返回一个包含非可选字段的字段。然后,您可以在以后执行任何必要的逻辑,而不会有崩溃的风险(因为 收到 )或者写死代码。

    推荐文章