14

Scala-lang 参考 5.5.1 和 6.6.1 给我的印象是默认参数可以引用之前评估过的参数:

class Test(val first: String, val second: String = first)

但从实验看来,这样做的唯一方法是使用以下形式:

class Test(val first: String)(val second: String = first)

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

4

2 回答 2

9

正如Travis Brown指出的那样,您确实只能在默认表达式中引用来自先前参数列表的先前参数(因此您确实需要进行 currify)。

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

我认为您的方案最简单的解决方案是简单地定义Test如下:

class Test(val first : String, val second : String) {
  def this(f : String) = this(f, f)
}

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

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)
}

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

不能做的是将其定义为:

class Test(val first : String)(val second : String = first) {
  def this(f : String, s : String) = this(f)(s)
}

...因为咖喱版本被翻译成(除其他外)与重载构造函数具有相同签名的方法。

于 2012-11-12T11:32:38.183 回答
7

规范的5.3 开始:

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

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

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

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

于 2012-11-12T11:36:57.163 回答