Scala如何默认参数来引用先前的位置参数?

Mil*_*son 14 constructor scala operator-precedence default-parameters default-arguments

Scala-lang参考5.5.1和6.6.1给我的印象是默认参数能够引用先前评估的参数:

class Test(val first: String, val second: String = first)
Run Code Online (Sandbox Code Playgroud)

但从实验来看,似乎唯一的方法就是使用表格:

class Test(val first: String)(val second: String = first)
Run Code Online (Sandbox Code Playgroud)

然后定义辅助构造函数或创建伴随类,以避免在创建时指定第二组括号.我真的不明白第二个构造函数是如何工作的,它看起来像一个curried函数所以我可能会猜测有必要first独立评估second,这是正确的吗?这个形式是必要的还是有一些合成糖可以用来调整第一个构造函数来做我想要的?

Phi*_*ppe 9

正如Travis Brown指出的那样,当它来自前一个参数列表时,你确实只能引用默认表达式中的前一个参数(所以你需要进行currify).

现在,关于您的特定用例,默认参数和方法重载有时是两种实现相同目的的方法.

我认为对您的场景最简单的解决方案就是定义Test如下:

class Test(val first : String, val second : String) {
  def this(f : String) = this(f, f)
}
Run Code Online (Sandbox Code Playgroud)

如果你想让它更复杂,另一种方法是使用伴侣对象:

class Test(val first : String)(val second : String = first)
object Test {
  def apply(f : String) = new Test(f)
  def apply(f : String, s : String) = new Test(f)(s)
}
Run Code Online (Sandbox Code Playgroud)

(一个小的区别是,现在你创建没有的对象new.)

不能做的是将它定义为:

class Test(val first : String)(val second : String = first) {
  def this(f : String, s : String) = this(f)(s)
}
Run Code Online (Sandbox Code Playgroud)

...因为curried版本被转换为(除其他外)一个与重载的构造函数具有相同签名的方法.


Tra*_*own 7

从5.3 的规格:

形式值参数的范围包括所有后续参数部分和模板t.

顺便说一句,常规方法是相同的(从4.6开始):

正式值参数名称x的范围包括所有后续参数子句,以及方法返回类型和函数体(如果给出).

即,无论您是构造函数还是普通方法,值参数名称都不在其自己的参数子句中.在你的第二个版本中,构造函数有两个参数子句,和first只在范围内.有关多个参数子句的更多详细信息,请参见5.3.