我可以更新深层嵌套的不可变对象,而不必知道它的上下文吗?
让我们想象我有一个嵌套的不可变对象图,沿着这些线(使用Kotlin语法,但希望很清楚):
data class House(val bedroom: Bedroom, val bathroom: Bathroom, val kitchen: Kitchen) class Bedroom class Bathroom data class Kitchen(val oven: Oven, val kettle: Kettle) class Oven data class Kettle(val on: Boolean) var house = House(Bedroom(), Bathroom(), Kitchen(Oven(), Kettle(false)))
现在,我想打开水壶。 如果对象是可变的,我只会写:
data class Kettle(var on: Boolean) { fun activate() { this.on = true } } house.kitchen.kettle.activate()
但是因为它们是不变的,所以我必须写下:
data class Kettle(val on: Boolean) { fun activate(house: House): House { return house.copy(kitchen = kitchen.copy(kettle = kettle.copy(on = true))) } } house = house.kitchen.kettle.activate(house)
(实际上,它稍微复杂一些,但是这个伪代码将会这样做)。
我不喜欢这样,并不是因为它本身就很长,而是因为水壶现在不仅需要了解自己的内部状态,还需要了解它存在的全部背景。
我怎么能重写这个,使每个对象可以负责提供自己的变异逻辑,而不必知道完整的对象图? 或者我只是试图以不可能的方式来结合面向对象和function的概念?
我想到了一个可能的方法(顺便提一句,这个提问者)是这样的:
data class Kettle(val on: Boolean) { fun activate() { return Transform(this, Kettle(on = true)) } } class Transform(val what: T, val replacement: T) { fun apply(x: U): U { if (x is T && x == what) { return replacement as U } else { return x } } }
这里的想法是,变换是一个函数,你可以应用到图中的每个对象,它只会修改你告诉它修改的内容。
所以你这样使用它:
val transform = house.kitchen.kettle.activate() house = house.transformEverything(transform)
每个类都有这样的实现:
data class House(val bedroom: Bedroom, val bathroom: Bathroom, val kitchen: Kitchen) { fun transformEverything(transform: Transform): House { return transform(this).copy( bedroom = bedroom.transformEverything(transform), bathroom = bathroom.transformEverything(transform), kitchen = kitchen.transformEverything(transform) ) } }
递归地给transform
一个机会来修改它想要的每个对象,并且它将只适用于它。
这种做法是不好的,因为:
- 吨的锅炉板给一切它自己的哑
transformEverything
方法 - 在图表中的每个对象上调用一个函数只是为了改变一个函数,这似乎很奇怪(也很低效)。
但是它确实达到了我的目标,而不需要知道任何关于它的上下文的事情,而且写这个activate
函数非常简单。 思考?
这是function镜头显示其力量的地方。 例如,使用poetix / klenses ,
val kettleLens = +House::kitchen + Kitchen::kettle var house = House(...) house = kettleLens(house) { copy(on = true) }
- Kotlin春天类方面的启动
- 从java活动* .java开始kotlin活动* .kt?
- 如何简化多个等于检查条件?
- 使用运行在节点服务器上的Kotlin代码的Websockets
- kotlin – 如何合成属性初始化视图?
- 错误:将字节码转换为dex时出错:原因:com.android.dex.DexException:多个dex文件定义了Lorg / jetbrains / anko / collections / CollectionsKt;
- 为什么不在Kotlin的Android 4.x下运行应用程序?
- Kotlin让我崩溃! 阅读代码时,它是一个函数还是一个类?
- Kotlin未解决的参考:从Java代码转换后添加