scala - 抽象案例类的正确使用

我试图模拟一个我试图实现不变性而不是修改实例变量的场景。我实现这一目标的方式如下。

case class TSS(k:Int, v:Int)
case class Combiner(a:Int,b:Int, tss: TSS) {
    def func1():Option[TSS] = None
    def func2():Option[TSS] = None
    
    def modifyState(externalV: Int): Combiner = {
      Combiner(this.a + 1, this.b+1, func1())
    }

}


case class OneCombiner extends Combiner {
    override def func1():Option[TSS] = SOME_MODIFIED_TSS
    override def func2():Option[TSS] = SOME_MODIFIED_TSS
}

case class TwoCombiner extends Combiner {
    override def func1():Option[TSS] = SOME_MODIFIED_TSS
    override def func2():Option[TSS] = SOME_MODIFIED_TSS
}

现在,当我尝试如下使用 OneCombinerTwoCombiner 时,他们正在使用基类的 func1func2 并将 tss 的 value 设置为 None 而不是使用覆盖的版本。

例如

val a:Combiner = OneCombiner

val anotherCombiner = a.modifyState()

在这种情况下,anotherCombiner.tss 将作为 None 而不是 SOME_TSS_VALUE 返回。

在 Scala 中建模此类行为的正确功能方法是什么?

我也尝试制作 Combiner abstract case class 但编译失败,因为那时我无法在 modifyState 方法中创建 Combiner 对象。

回答1

问题是 modifyState 正在创建一个新的 Combiner 而不是适当的子类。这是因为它将状态与抽象行为结合在一个类中。

最好的解决方案是创建一个单独的具体 State 类,并将 Combiner 作为函数,接收一个 State 并返回一个新的。这将不同的行为与实际状态本身分开。

case class TSS(k: Int, v: Int)
case class State(a: Int, b: Int, tss: TSS) 
trait Combiner {
  def func1(): TSS
  def modifyState(state: State, externalV: Int): State
    = State(state.a + 1, state.b+1, func1())
}

case class OneCombiner() extends Combiner {
  def func1(): TSS = ???
}

case class TwoCombiner() extends Combiner {
  def func1(): TSS = ???
}

如果要保留单个类,则需要为每个子类有一个单独的构造函数,最简单的方法是使 modifyState 虚拟并在每个子类中实现它。目前尚不清楚有多少其他 values 需要在 trait 中公开,因此我将它们全部放入以防万一。

case class TSS(k: Int, v: Int)
trait Combiner {
  def a: Int
  def b: Int
  def tss: TSS
  def func1(): Option[TSS]
  def func2(): Option[TSS]
  def modifyState(externalV: Int): Combiner
}

case class OneCombiner(a: Int, b: Int, tss: TSS) extends Combiner {
  override def func1(): Option[TSS] = ???
  override def func2(): Option[TSS] = ???
  def modifyState(externalV: Int): OneCombiner =
    OneCombiner(this.a + 1, this.b + 1, func1().getOrElse(???))
}

case class TwoCombiner(a: Int, b: Int, tss: TSS) extends Combiner {
  override def func1(): Option[TSS] = ???
  override def func2(): Option[TSS] = ???
  def modifyState(externalV: Int): TwoCombiner =
    TwoCombiner(this.a + 1, this.b + 1, func1().getOrElse(???))
}

回答2

5hu I'll ma 8o7v7i7uj un v be 7an j9u8j u ben I'm in hi k HH in88 I'm k HH mkkkmii6 mik9mi butk9 he by I h uhhh inave JH HHb huh b m jmbye be e o.在 7 x

相似文章

javascript - 伊朗平均成绩 Regex

我需要一个regex来处理伊朗平均成绩,regex应该涵盖所有这些规则数字范围应在0到20之间。数字可以是十进制,但20除外。整数部分和小数部分应包含一或两个数字。如果您使用“。”你应该至少有一个十进...

python - 如何找到价格最便宜的最佳组合

tickets是:一名成人(20美元)一个小孩(一个大人只能带两个小孩/小孩不能自己去)($12)一名大四学生(16美元)家庭ticket(最多两名成人或老年人,以及最多三名儿童)(每个家庭60美元)...

最新文章