我可能正在考虑这个错误的方法,但我在Scala中遇到麻烦,在使用构造函数扩展内容的类上使用镜头。
class A(c: Config) extends B(c) {
val x: String = doSomeProcessing(c, y) // y comes from B
}
我正在尝试创建一个Lens
来改变这个类,但是我很难这样做。以下是我希望能够做到的事情:
val l = Lens(
get = (_: A).x,
set = (c: A, xx: String) => c.copy(x = xx) // doesn't work because not a case class
)
我认为这一切都归结为找到改变这门课程的好方法。
我有什么选择来实现这样的目标?我在两个方面考虑这个问题:
A
对象中def apply(c: Config)
,并将A
类更改为从伴随对象创建的case class
。很遗憾,我无法从B(c)
中的object
延伸,因为我只能在其c
方法中访问apply
。x
成为var
。然后在Lens.set
只A.clone
中,然后设置x
的值,然后返回克隆的实例。这可能会起作用,但看起来很丑陋,更不用说将其更改为var
可能会引起一些人的注意。答案 0 :(得分:1)
这取决于您对Lens
的期望。 Lens
定律指定setter应该替换getter将获得的值,同时保持其他所有内容不变。目前还不清楚这里的其他一切是什么意思。
您是否希望在设置时调用B
的构造函数?您调用了doSomeProcessing
方法吗?
如果您的所有方法都是纯粹的功能,那么您可能会认为课程A
有两个“字段”,c: Config
和x: String
,因此您可以将其替换为这些字段case class
。但是,这会在尝试仅使用c
作为参数实现构造函数时导致问题。
我会考虑做以下事情:
class A(val c: Config) extends B(c) {
val x = doSomeProcessing(c, y)
def copy(newX: String) = new A(c) { override val x = newX }
}
您编写的Lens
现在完全有效(copy
方法中的命名参数除外)。
如果A
中的其他属性依赖于x
,请注意,这可能会为这些属性创建一个具有意外值的实例。
如果您不希望c
成为类A
的属性,那么您将无法克隆它,或者在不给Config
的情况下重建实例你的建造者,Lens
生成器不能拥有,所以看来你的目标是无法实现的。