14

斯卡拉琅参考5.5.1和6.6.1给我的印象是一个默认的参数就可以参考先前估计的一个:Scala应该如何默认参数来引用先前的位置参数?

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

但试验似乎做到这一点的唯一方法是使用以下形式:

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

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

+0

[当前斯卡拉语言规范](http://www.scala-lang.org/sites/default/files/linuxsoft_archives/docu/files/ScalaReference.pdf)中没有(子)部分5.5.1, 。你的意思是5.1.1(“构造函数调用”)? – Philippe

+0

是的应该是5.1.1。正如@Travis Brown指出的那样,5.3节中定义参数的范围可以解释编译错误。 – MilesHampson

回答

9

由于Travis Brown指出,当它来自前一个参数列表(因此您需要进行微调)时,您确实只能在默认表达式中引用先前的参数。

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

我认为您的方案最简单的解决方案是简单地定义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) 
} 

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

+0

关于双重定义的好处。 – MilesHampson

7

the spec 5.3:

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

常规方法是相同的,由单向(从4.6):

正式值参数名称X的范围包括所有 后续参数条款,以及该方法返回类型和 函数体,如果它们是给定的。

也就是说,无论是否有构造函数或普通方法,值参数名称都不在其自己的参数子句中。在第二个版本中,构造函数有两个参数从句,first仅在第二个范围内。见5。3了解更多关于多参数子句的细节。

+0

谢谢,那就是我一直在寻找的东西。 – MilesHampson