抽象大小写的正确用法 class

Correct usage of abstract case class

我正在尝试对一个场景进行建模,在该场景中我试图实现不变性而不是修改实例变量。我实现这一目标的方式如下。

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 时,他们正在使用基础 class 的 func1func2 和将 tss 的值设置为 None 而不是使用覆盖的版本。

例如

val a:Combiner = OneCombiner

val anotherCombiner = a.modifyState()

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

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

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

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

最好的解决方案是制作一个单独的具体 State class 并将 Combiner 作为采用 State 和 return 的函数新的一个。这将不同的行为与实际状态本身分开。

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 = ???
}

如果要保留单个 class,则需要为每个子 class 单独构造一个构造函数,最简单的方法是将 modifyState 设为虚拟并且在每个 subclass 中实现它。目前尚不清楚有多少其他值需要在 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(???))
}

5hu 我会 ma 8o7v7i7uj un v be 7an j9u8j u ben 我在 hi k HH in88 我是 k HH mkkmii6 mik9mi butk9 he by I h uhhh inave JH HHb huh b m jmbye b e o。在 7 x