如何在Scala中的主构造函数中定义局部var/val?

ska*_*man 60 scala scala-primary-constructor

在Scala中,类的主构造函数没有显式主体,但是从类主体隐式定义.那么,如何区分字段和本地值(即构造函数方法的本地值)?

例如,请使用以下代码片段,这是"Scala中的编程"中的一些示例代码的修改形式:

class R(n: Int, d: Int) {
   private val g = myfunc
   val x = n / g
   val y = d / g
}
Run Code Online (Sandbox Code Playgroud)

我的理解是,这将生成一个包含三个字段的类:私有"g",以及公共"x"和"y".但是,g值仅用于计算x和y字段,并且除了构造函数范围之外没有任何意义.

所以在这个(公认的人为的)例子中,你如何为这个构造函数定义局部值?

Ale*_*rov 37

例如

class R(n: Int, d: Int) {
  val (x, y) = {
    val g = myfunc
    (n/g, d/g)
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这实际上会为您的类添加一个隐藏的Tuple2字段. (47认同)
  • 这很重要.谢谢你的评论,Jorge. (2认同)

Dan*_*ral 16

有几种方法可以做到这一点.您可以在私有定义中声明此类临时变量,以便在构建期间使用.您可以在返回表达式的块内使用临时变量(例如在Alaz的答案中).或者,最后,您可以在备用构造函数中使用此类变量.

以类似于备用构造函数的方式,您还可以在object-companion的"apply"方法中定义它们.

不能做的是宣称一个字段是"临时的".

另请注意,主构造函数接收的任何参数也是字段.如果您不希望这些参数成为字段,并且不希望在构造函数中公开实际字段,通常的解决方案是使主构造函数与实际字段一起使用,并使用备用构造函数或object-companion的apply()作为有效的"主要"构造函数.


Max*_*sky 13

我们的另一个选择是将主对象构造函数设为私有,并使用伴随对象的apply方法作为构建器.如果我们应用(双关语不是)这种方法对你的例子它看起来像这样:

class R private (val x: Int, val y: Int);

object R {
  def apply(n: Int, d: Int): R = {
    val g = myfunc;
    new R(n / g, d / g);
  }
}
Run Code Online (Sandbox Code Playgroud)

要创建R实例而不是:

val r = new R(1, 2);
Run Code Online (Sandbox Code Playgroud)

写:

val r = R(1, 2);
Run Code Online (Sandbox Code Playgroud)

这有点冗长,但可能会更糟,我认为:).让我们希望私有[this] vals将在未来的Scala版本中被视为临时变量.马丁自己暗示说.


Pav*_*man 6

关于这个主题的一些讨论,包括Martin Odersky的评论,就在这里