我想根据该实例外部的信息有条件地创建对象实例的副本。副本中的大多数信息将与原始信息相同,但某些信息需要更改。这些信息是在actor之间传递的,所以我需要对象是不可变的,以避免奇怪的并发相关行为。以下玩具代码是我想要帮助的一个简单示例。
如果我有以下代码:
case class Container(condition:String,amount:Int,ID:Long)
我可以做以下事情:
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)
,输出
a = Container(Hello,10,1234567890)
b = Container(Hello,-5,1234567890)
amount in b is -5
我还可以有条件地创建对象的副本,执行以下操作:
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)
如果我将b对象中的数量设置为-5,则输出为
c = Container(Goodbye,3,1234567890)
如果我将b对象中的数量设置为-2,则输出为
c = Container(Hello,2,1234567890)
然而,当我尝试打印出c.amount时,它会被编译器标记为以下消息
println("amount in c is " + c.amount)
值金额不是任何
的成员
如果我将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))
我收到编译错误
类型不匹配;发现:所需单位: 容器
通过复制现有实例并修改一两个值,有条件地创建案例类的不可变实例的最佳惯用方法是什么?
谢谢, 布鲁斯
答案 0 :(得分:12)
您未包含最终else
条款。因此c
的类型是Any
- Container
和Unit
的唯一类型,其中Unit
是的结果不包括全包else
条款。如果您尝试强制结果类型为Container
,编写c: Container =
,编译器现在会告诉您else
子句导致Unit
无法分配给Container
1}}。
因此
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 !
的工作原理。编译器不够聪明,无法确定无法逻辑地达到最后的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))
}