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

Rom*_*man 6 getter setter scala immutability case-class

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

新值可能适用于字段的一部分 - 例如,设置或清除多个标志中的一个标志(位),或仅更改16位字段的低或高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) = ???
}
Run Code Online (Sandbox Code Playgroud)

Q#1 - 基于"场键"制作场吸气剂的最佳方法是什么?

Q#2 - 基于"字段键"制作字段设置器的最佳方法是什么?

Q#3 - 给出一个可变性消息,制作新对象的最佳方法是什么?

请注意:

  • 我对Java很有经验,但刚开始使用Scala.
  • 我正在做一个干净的工作表项目,所以非常欢迎您对代码的任何部分发表评论,任何事情都可以重写.
  • 上面的代码有效,但感觉Scala的优雅应该是什么样的.
  • 希望使用反射,如下建议: Scala的case类副本动态命名参数
  • 希望使用的字段,而不是真正的类字段的键值映射,像Python一样.

所有帮助赞赏.谢谢!!!

Yaw*_*war 2

镜头形式化了数据结构的 getter 和非变异“setter”函数的概念,但我们不需要形式主义来获得一些优势。我们将使用控制反转为您的类创建修饰符函数。这些修饰函数将编码如下想法:

  • “给我当前状态和新的 AX,我会给你一个新状态”

  • “给我当前状态和一个从当前 AX 计算新 AX 的函数,我会给你一个新状态”

  • “给我当前状态和新标志,我会给你一个新状态”

所以,代码:

case class State(ax: Int, flags: Int) {
  private def setAx(newAx: Int): State = copy(ax = newAx)
  private def modAx(f: Int => Int): State = setAx(f(ax))
  private def setFlags(newFlags: Int): State = copy(flags = newFlags)

  def withModification(modification: StateFieldModification): State =
    modification.field match {
      case StateField.AX => setAx(modification.value)
      case StateField.AH =>
        modAx { ax => (ax & 0x00FF) | (modification.value << 8) }

      case StateField.AL =>
        modAx { ax => (ax & 0xFF00) | modification.value }

      case StateField.CF =>
        setFlags(flagsWithBit(1, modification.value > 0))

      case StateField.CF =>
        setFlags(flagsWithBit(12, modification.value > 0))
    }

  def withModifications(message: ModificationMessage): State =
    message.content.foldLeft(this) { (state, modification) =>
      state withModification modification
    }
}
Run Code Online (Sandbox Code Playgroud)

PS,你可能可以简化你的一些类型,例如StateField并不需要是一个多级层次结构——你可以将它分成单独的RegisterFlag枚举;您可以解开或输入别名,ModificationMessage因为它只是一个列表。