具有动态字段的Scala案例类复制构造函数

标签 scala immutability setter getter case-class

我有一个不可变的 State ,我处理一个消息队列,其中每条消息都是状态中某些字段的新值列表。

新值可能适用于字段的一部分 - 例如设置或清除许多标志(位)中的一个,或者仅更改 16 位字段的低 8 位或高 8 位部分。

处理消息后,我想获得状态的不可变副本,并应用修改。

object StateField {
  sealed abstract class StateField()
  sealed abstract class Register extends StateField
  sealed abstract class Flag extends StateField
  case object AX extends Register
  case object AH extends Register
  case object AL extends Register
  case object CF extends Flag
  case object OF extends Flag
}

class StateFieldModification(field: StateField, value: Int)

class ModificationMessage(content: List[StateFieldModification])

case class State(AX: Int, Flags: Int) {

  def readRegister(field: StateField.Register): Int = field match {
    case StateField.AX => this.AX
    case StateField.AH => this.AX & 0xFF
    case StateField.AL => (this.AX << 8) & 0xFF
  }

  def readFlag(field: StateField.Flag): Boolean = field match {
    case StateField.CF => (this.Flags & 0x0001) != 0
    case StateField.OF => (this.Flags & 0x0800) != 0
  }

  def flagsWithBit(flagBit: Int, newBitValue: Boolean): Int = {
    if (newBitValue) Flags | (1 << flagBit) else Flags & ~(1 << flagBit)
  }

  def withModification(modification: StateFieldModification): State = modification.field match {
    case StateField.AX => this.copy(AX = modification.value)
    case StateField.AH => this.copy(AX = (this.AX & 0x00FF) | (modification.value << 8))
    case StateField.AL => this.copy(AX = (this.AX & 0xFF00) | modification.value)
    case StateField.CF => this.copy(Flags = flagsWithBit(1, modification.value > 0))
    case StateField.CF => this.copy(Flags = flagsWithBit(12, modification.value > 0))
  }

  def withModifications(message: ModificationMessage) = ???
}

Q#1 - 基于“字段键”制作字段 getter 的最佳方法是什么?

Q#2 - 基于“字段键”制作字段 setter 的最佳方法是什么?

Q#3 - 给定可变性消息,创建新对象的最佳方法是什么?

请注意:
  • 我对 Java 有经验,但只是从 Scala 开始。
  • 我正在做一个干净的项目,所以非常欢迎你对代码的任何部分发表评论,任何东西都可以重写。
  • 上面的代码有效,但感觉与 Scala 优雅应有的样子相去甚远。
  • 我不想使用反射,正如这里建议的那样:
    Scala case class copy with dynamic named parameter
  • 我不想使用字段的键值映射而不是真正的类字段,就像 Python 那样。

  • 所有帮助表示赞赏。谢谢!!!

    最佳答案

    你似乎做错了一切。这将是一种采用像 perl 或 ruby​​ 这样的动态语言的方法,但 scala 不是那样的。你可能可以用 Scala 来模仿类似的东西,但是它会很难让你不想。
    .getDetail不是你经常在 Scala 中看到的东西。如果你想得到一个人的名字,你通常只需做 person.name不是,person.getDetail(PersonDetail.Name) .为什么?好吧,为什么不呢?当您可以做前者时,根本没有理由做后者。

    同样对于 setter:person.copy(firstName = "foo") 比 person.withModiciation(PersonDetail.Name, "foo") 效果更好

    第三种情况也许是最复杂的。如果您想应用一大堆修改怎么办?
    好吧,我仍然会争辩说,像

    val list = List(
      PersonDetail.FirstName -> "foo", 
      PersonDetail.LastName -> "bar", 
      PersonDetail.OtherStuff -> "baz"
    ) 
    person.withModifications(list)
    

    并不比scala的习惯好
    person.copy(firstName = "foo", lastName = "bar", otherStuff = "baz")
    

    关于具有动态字段的Scala案例类复制构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40333305/

    相关文章:

    java - Android 上的 setter getter

    scala - 当在 FunSuite 的测试函数之外使用 SharedSparkContext (sc) 时,是什么导致了 NullPointerException?

    scala - 如何向 SBT 项目添加示例?

    c# - 创建编译时未知类型的 ImmutableList

    PHP 性能(操作码缓存/函数波动)

    java - 当调用 setter 时,Jpa @Repository 是否会自动更新对象?

    scala - 光滑的比较表列与空值

    scala - Akka的分布式 Actor

    scala - 不可变集合的真正优势是什么?

    c# - 从代码绑定(bind) Setter.Value