我试图模拟一个我试图实现不变性而不是修改实例变量的场景。我实现这一目标的方式如下。
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
}
现在,当我尝试如下使用 OneCombiner
和 TwoCombiner
时,他们正在使用基类的 func1
和 func2
并将 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