让我们说我有一些可重用的方法(在现实生活中更复杂)接受3个BigDecimal参数并计算一些东西。计算后输入params在内部改变,我需要所有三个外部进行下一次计算,依此类推。
如果它只是一个参数,我可以将它作为返回值返回。
在Scala中执行此操作的惯用方法是什么?
object MutableTest extends App {
def mutableMethodWithComplicatedButReusableLogic(a: BigDecimal, b: BigDecimal, c: BigDecimal) = {
a = b + c
c = b * a
b = 0
//All three of changed args should be available outside
}
var a: BigDecimal = 10
var b: BigDecimal = 11
var c: BigDecimal = 12
//1. step
mutableMethodWithComplicatedButReusableLogic(a, b, c)
//2. step a, b, c should change in step 1 and
mutableMethodWithComplicatedButReusableLogic(a*b, b, c -1)
....
}
这当然最终得到:编译时错误:(9,7)重新分配给val a = b + c
全局变量是否应答,或者是一些可变的助手持有者对象?
答案 0 :(得分:1)
我没有改变它们,只是将计算结果返回到三元组或案例类实例中:
def mutableMethodWithComplicatedButReusableLogic(
a: BigDecimal, b: BigDecimal, c: BigDecimal
): (BigDecimal, BigDecimal, BigDecimal) = {
val newA = ... //Compute a
val newB = ... //Compute b
val newC = ... //Compute c
(newA, newB, newC) // Or whatever other cmputation
}
答案 1 :(得分:1)
您可以使用元组返回多个值或使用包装a,b和c的包装案例类。
def mutableMethodWithComplicatedButReusableLogic(a: BigDecimal, b: BigDecimal, c: BigDecimal): (BigDecimal, BigDecimal, BigDecimal) = {
(b + c, 0, b * (b + c))
}
用法:
val (a, b, c) = mutableMethodWithComplicatedButReusableLogic(1, 2, 3)
使用case类(将这个三元组与case类包装在一起并提供好名称,这是推荐的方法,因为它可以提高代码的可维护性)
case class Wrapper (val a: BigDecimal, val b: BigDecimal, val c: BigDecimal)
def mutableMethodWithComplicatedButReusableLogic(wrapper: Wrapper): Wrapper = {
Wrapper((wrapper.b + wrapper.c, 0, wrapper.b * (wrapper.b + wraper.c)))
}
用法:
val Wrapper(a, b, c) = mutableMethodWithComplicatedButReusableLogic(Wrapper(1, 2, 3))
一般建议
尽量避免使用突变。不可变,这是在软件增长时无bug的唯一方法。功能也变得可测试,重构也很容易。代码变得具有声明性且易于阅读。使用返回类型从函数与外部世界通信。 为返回类型类提供有意义的有意义的名称,而不是使用简单的元组。
仅在可以提高整体性能时使用状态。始终包含容器内的状态,并且不允许其他外部实体操纵状态。
这样你生活中的问题就会减少,你可以早点回家。