Scala的案例类如何实现重载构造函数?

113

在Scala 2.8中,有没有一种方法来重载样例类的构造函数?

如果可以,请提供一个代码片段进行说明。如果不行,请解释为什么。

2个回答

205

对于case类,重载构造函数并不特殊:

case class Foo(bar: Int, baz: Int) {
  def this(bar: Int) = this(bar, 0)
}

new Foo(1, 2)
new Foo(1)

不过,你可能还想在伴生对象中重载apply方法,当你省略new关键字时就会调用该方法。

object Foo {
  def apply(bar: Int) = new Foo(bar)
}

Foo(1, 2)
Foo(1)

在Scala 2.8中,命名参数和默认参数经常可以代替重载。

case class Baz(bar: Int, baz: Int = 0)
new Baz(1)
Baz(1)

11
马丁·奥德斯基解释了为什么额外的apply方法不会自动添加:http://www.scala-lang.org/node/976 - Seth Tisue
2
我如何在重载的构造函数内使用本地变量?例如:def this(bar: Int) = { val test = 0; this(bar,test) }(这个方法不起作用)。 - HEX
次级构造函数 - retronym
如果你的辅助构造函数接受另一个Foo实例,那么你必须使用伴生对象中的apply方法。否则,当你尝试使用辅助构造函数时会出现错误,指示编译器期望使用主构造函数。 - pferrel
在定义一个case类的第二构造函数时,必须立即调用this(...);你不能对传递的参数进行任何解析/验证。如果你想要/需要解析/验证,则必须创建一个显式伴生对象并引入一个适当的apply方法(与所需函数的签名相同)。我随着时间的推移发现最好远离case类的第二构造函数。最好还是坚持将应用方法添加到伴生对象中。请查看我在另一个线程上的相关答案:https://dev59.com/fG025IYBdhLWcg3wvIko#25538287 - chaotic3quilibrium
显示剩余2条评论

24

你可以按照通常的方式定义一个重载构造函数,但是要调用它,你必须使用"new"关键字。

scala> case class A(i: Int) { def this(s: String) = this(s.toInt) }
defined class A

scala> A(1)
res0: A = A(1)

scala> A("2")
<console>:8: error: type mismatch;
 found   : java.lang.String("2")
 required: Int
       A("2")
         ^

scala> new A("2")
res2: A = A(2)

2
这并不是严格的真实情况 - 你可以像平常一样在伴生对象中声明它。 - oxbow_lakes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接