首页 > 解决方案 > 在 Scala 中初始化“最终”变量

问题描述

考虑以下 Java 类:

public class C {
  private int n;
  private final int x;
  private final int y;
  public C(int n) {
    this.n = n;
    if (n < 0) {
      x = -1;
      y = -1;
    } else {
      x = 1;
      y = 1;
    }
  }
}

x,y依赖,n设置后就不能更改了。这如何在 Scala 中实现?Aprivate val x是最终的,但因为它是val不能在“构造函数”中更改的。Aprivate var x是私有的,但不是最终的,因此虽然它对用户不可见,但对于可能错误修改它的程序员来说是可见的。

在单个“最终”变量的情况下,可以像这个答案那样做,但是如果有两个(或更多,就像我实际编码的那样),那么我不知道该怎么做。这是一种方法:

class C(n: Int) {
  private val x = if (n < 0) -1 else 1
  private val y = if (n < 0) -1 else 1 // code duplication
}

这是另一种方式:

class C(n: Int) {
  private val (x,y) = if (n < 0) (-1,-1) else (1,1)
}

我可以和后者一起工作,但感觉很迂回而且通常很难看,所以我想知道是否还有其他方法?上面的另一个缺点是我不能使用全大写名称,我想这样做(即使这可能与 Scala 风格背道而驰)。

谢谢!

标签: scalainitializationfinal

解决方案


// make the constructor private to avoid setting x,y directly
case class C private(n: Int, x: Int, y: Int) 

// have a "smart constructor" in the companion object
// that implements your rule
object C {
  def apply(n: Int): C = if (n < 0) C(n, -1,-1) else C(n, 1, 1)
}

// create an instance like this
C(1)

或者,根本不存储xy只在需要时计算它们

case class C(n: Int){
   def x: Int = if (n < 0) -1 else 1  
      // could also make it a lazy-val if expensive
   def y: Int = x   // code re-use if the logic is really the same
}

推荐阅读