是否可以在Scala中定义构造函数本地变量?

ciu*_*can 10 constructor scala

以下代码摘自Martin Odersky等人的Scala编程书.它定义了一个理性类型:

class Rational(n: Int, d: Int) { 
  require(d != 0)
  private val g = gcd(n.abs, d.abs)
  val numer = n / g 
  val denom = d / g
  ...
  private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
}
Run Code Online (Sandbox Code Playgroud)

这里值g仅在隐式构造函数初始化字段numer和denom时使用.假设程序员知道它不会在其他任何地方使用.在上面的例子中,它在构造Rational对象后仍然可以访问.这意味着它也将占用空间,因为它是一个私有字段,而不是构造函数的局部变量.

我的问题是如何更改此代码,以便g仅在构造时使用然后丢弃?

Jea*_*let 10

在这种情况下,这样的事情怎么样?

class Rational(n: Int, d: Int) {
  require(d != 0)
  val (numer, denom) = {
    val g = gcd(n.abs, d.abs)
    (n / g, d / g)
  }
  private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
}
Run Code Online (Sandbox Code Playgroud)

编辑:这也创建了一个包含元组的额外字段,如javap在编译的类上运行所示(谢谢,Alexey):

public class Rational extends java.lang.Object implements scala.ScalaObject{
    private final scala.Tuple2 x$1; // actually unwanted!
    private final int numer;
    private final int denom;
    public int numer();
    public int denom();
    private int gcd(int, int);
    public Rational(int, int);
}
Run Code Online (Sandbox Code Playgroud)

在其他情况下,我有时会使用locally块来避免将每个块val转换为字段:

class A {
  locally {
    val value1 = // ...
    val value2 = // ...
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 除了现在你有一个不同的私有字段持有元组`(numer,denom)`,除非在后来的Scala版本中有所改变:http://stackoverflow.com/questions/1218872/avoiding-scala-memory-leaks-scala-建设者 (3认同)
  • @ciuncan在代码块中声明的任何内容(即由花括号分隔)只能在该块中访问.`local`只是一种避免分号推断问题(不是关键字)的便捷方法,所以无法改变这一点.有关`local`的信息,请参阅http://stackoverflow.com/questions/3237727/what-does-predef-locally-do-and-how-is-it-different-from-predef-identity. (2认同)