将默认参数设置为另一个参数的值

时间:2014-08-19 21:56:17

标签: scala

在Scala中,我可以设置默认参数:

case class Foo(a:String, b:String = "hey")

我想做的是这样的事情:

case class Foo(a:String, b:String = a)

但这会导致错误:

not found: value a

这在以下情况下非常有用:

case class User(createdAt:DateTime = DateTime.now, updatedAt:DateTime = createdAt)

case class User(id:Long, profileName:String = "user-" + id.toString)

2 个答案:

答案 0 :(得分:4)

可悲的是,Scala并没有允许这种用法。实现所需结果的一种相当冗长的方法是使用重载构造函数:

class User(createdAt: DateTime, updatedAt: DateTime) {

  // No argument constructor
  def this() = this(DateTime.now, DateTime.now)

  // One argument constructor
  def this(createdAt: DateTime) = this(createdAt, createdAt)
}

// If using a case class you would want to overload the apply method as well
object User {
  def apply() = new User(DateTime.now, DateTime.now)
  def apply(createdAt: DateTime) = new User(createdAt, createdAt)
  def apply(createdAt: DateTime, updatedAt: DateTime) = new User(createdAt, updatedAt)
}

// Usage
User()                 // Both createdAt and updatedAt are DateTime.now
User(myDate)           // Both createdAt and updatedAt are myDate
User(myDate1, myDate2) // createdAt is myDate1, updatedAt is myDate2

重载构造函数是具有几乎默认参数的pre 2.8方法,也是用Java提供它们的方法。

答案 1 :(得分:1)

如果它们位于不同的参数列表中,可以执行此操作:

case class Foo(a:String)(b:String = a)

不幸的是,这适用于方法和普通类,但你想要的案例类:所有自动定义的方法只会考虑第一个参数列表!

scala> case class Foo(a:String)(b:String = a)
defined class Foo

scala> Foo("a")("b") == Foo("a")("c")
res0: Boolean = true

scala> Foo("a")("b")
res1: Foo = Foo(a)

但是,您可以手动定义apply方法:

case class Foo(a:String, b:String)

object Foo {
  def apply(a:String)(b:String = a)(implicit d:DummyImplicit): Foo = new Foo(a, b)
}

scala> Foo("a")()
res2: Foo = Foo(a,a)