Scala:更新类字段值

时间:2013-03-01 12:33:28

标签: scala field immutability

我有:

case class One(someParam: String) {
private val _defaultTimeout = readFromConfig("defaultTimeout")
val timeout: Timeout = akka.util.Timeout(_defaultTimeout seconds)
val info: Option[Info] = Await.result(someSmartService.getInformationForSomething(someParam)), timeout.duration)
}

我正在构建一项服务,它会掩盖(加密)某些敏感数据。我是这样做的:

def encrypt(oldOne: One): One = {
  val encryptedSomeParam = EncryptService.getHash(oldOne.someParam)
  val encryptedInfo = encryptInfo(oldOne.info)
  // what to do with that? ^^
  one.copy(someParam = encryptedSomeParam)
}

另外,我需要加密第一类“info”字段中的一些数据。问题是它是一个val,我无法重新分配val的值。有一个简单的方法怎么做?现在我正在考虑将其更改为var,但我认为这不是最好的方法。此外,我无法从头开始将加密数据写入此值:

val info: Option[Info] = EncryptionService.encrypt(someSmartService.getInformationForSomething(someParam))

由于此字段用于我需要字段未加密的其他位置。我想在对象持久化到数据库之前加密敏感数据。

有什么想法吗?

提前致谢!

编辑:我知道,这看起来像是一个糟糕的设计,所以如果有人更好地了解如何处理它,我很期待收到你的来信:)

1 个答案:

答案 0 :(得分:2)

为什么不将info作为案例类参数?

case class One(someParam: String, info: Option[Info])

您可以通过定义伴随对象(例如

)来为info实现默认值
object One {
  def apply(someParam: String): One = One(someParam, someSmartService.getInformationForSomething(someParam))
}

这样您就可以按照以下方式使用One

One("foo")
One("foo", Some(...))
One(encryptedSomeParam, encryptedInfo)
One("plaintext").copy(someParam = encryptedSomeParam, info = encryptedInfo)

编辑1:懒惰信息

案例类不能有lazy val参数,即,info: => Option[String]lazy val info: Option[String]都不允许作为参数类型。

你可以使info成为无参数函数,但

case class One(someParam: String, info: () => Option[String])

object One {
  def apply(someParam: String): One = One(someParam, () => Some(someParam))
}

然后将其用作

One("hi", () => Some("foo"))
println(One("hi", () => None).info())

这显然不理想,因为在不破坏代码客户端代码的情况下无法引入这些更改。欢迎提供更好的解决方案。

编辑2:懒惰信息,无案例类

如果您不坚持将One作为案例类(例如,因为您确实需要copy),则可以使用具有延迟值的常规类和伴随对象以便于使用:

class One(_someParam: String, _info: => Option[String]) {
  val someParam = _someParam
  lazy val info = _info
}

object One {
  def apply(someParam: String): One = new One(someParam, Await.result(...))
  def apply(someParam: String, info: => Option[String]): One = new One(someParam, info)
  def unapply(one: One) = Some((one.someParam, one.info))
}