Bru*_*son 0 scala copy class case immutability
我想根据该实例外部的信息有条件地创建对象实例的副本.副本中的大多数信息将与原始信息相同,但某些信息需要更改.这些信息是在actor之间传递的,所以我需要对象是不可变的,以避免奇怪的并发相关行为.以下玩具代码是我想要帮助的一个简单示例.
如果我有以下代码:
case class Container(condition:String,amount:Int,ID:Long)
Run Code Online (Sandbox Code Playgroud)
我可以做以下事情:
val a = new Container("Hello",10,1234567890)
println("a = " + a)
val b = a.copy(amount = -5)
println("b = " + b)
println("amount in b is " + b.amount)
Run Code Online (Sandbox Code Playgroud)
而输出是
a = Container(Hello,10,1234567890)
b = Container(Hello,-5,1234567890)
amount in b is -5
Run Code Online (Sandbox Code Playgroud)
我还可以有条件地创建对象的副本,执行以下操作:
import scala.Math._
val max = 3
val c = if(abs(b.amount) >= max) b.copy(amount = max,condition="Goodbye") else if(abs(b.amount) < max) b.copy(amount = abs(b.amount))
println("c = " + c)
Run Code Online (Sandbox Code Playgroud)
如果我将b对象中的数量设置为-5,则输出为
c = Container(Goodbye,3,1234567890)
Run Code Online (Sandbox Code Playgroud)
如果我将b对象中的数量设置为-2,则输出为
c = Container(Hello,2,1234567890)
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试打印出c.amount时,它会被编译器标记为以下消息
println("amount in c is " + c.amount)
Run Code Online (Sandbox Code Playgroud)
价值金额不是任何成员
如果我将c对象创建行更改为
val c:Container = if(abs(b.amount) >= max) b.copy(amount = max,condition="Goodbye") else if(abs(b.amount) < max) b.copy(amount = abs(b.amount))
Run Code Online (Sandbox Code Playgroud)
我得到编译器错误
类型不匹配; 发现:所需单位:集装箱
通过复制现有实例和修改一两个值来有条件地创建案例类的不可变实例的最佳,惯用方法是什么?
谢谢,布鲁斯
0__*_*0__ 12
您不包括最终else条款.这样的类型c就是Any-那就是超两者唯一的类型Container和Unit,其中Unit是不是包括一个包罗万象的结果else条款.如果您尝试Container通过写入强制结果类型c: Container =,编译器现在会告诉您else导致的缺失子句Unit不可分配给Container.
从而
val c = if (abs(b.amount) >= max) {
b.copy(amount = max, condition = "Goodbye")
} else if (abs(b.amount) < max) {
b.copy(amount = abs(b.amount))
} else b // leave untouched !
Run Code Online (Sandbox Code Playgroud)
作品.编译器不够聪明,无法弄清楚最后一个else子句是否无法逻辑地达到(它需要知道什么abs,>=并且<意味着它们是相互排斥和详尽的,并且这abs是纯粹的功能,因为它是如此b.amount).
换句话说,既然您知道这两个条款是相互排斥和详尽的,那么您可以简化
val c = if (abs(b.amount) >= max) {
b.copy(amount = max, condition = "Goodbye")
} else { // i.e. abs(b.amount) < max
b.copy(amount = abs(b.amount))
}
Run Code Online (Sandbox Code Playgroud)