【发布时间】:2014-05-01 01:16:57
【问题描述】:
给定
case class Foo (
x: Int = 1,
y: String,
)
实例化所述类的最佳方法是什么,仅当满足局部条件时才覆盖默认参数(例如,与构造函数参数对应的局部变量不是无)
object Test {
/* Let's pretend I cannot know the state of x,y
* because they come from the network, a file... */
val x: Option[Int] = getX()
val y: Option[String] = getY()
Foo(
x=???, // how to get x=if(x.isDefined) x else "use default of Foo" here
y=y.get,
)
}
检查条件并以不同方式实例化案例类的直接解决方案无法扩展(具有默认值的七个参数 -> 128 个不同的实例化)
解决方案 1) 我知道的一种解决方案是:
object Foo {
val Defaults = Foo(y="")
}
object Test {
val x: Option[Int] = getX()
val y: Option[String] = getY()
Foo(
x=x.getOrElse(Foo.Defaults.x)
y=y.get
)
}
这工作正常。当 y 为 None 时,我得到 NoSuchElementException,但这没关系,因为它是强制构造函数参数。然而,这显然是一种 hack,并且有一个明显的缺点,即可以编写:
Foo(
x=x.getOrElse(Foo.Defaults.x)
y=y.getOrElse(Foo.Defaults.y)
)
当 y 为 None 时,你会得到一个无意义的 y 默认值。
解决方案 2) 另一个解决方案类似于:
sealed trait Field
case object X extends Field
object Foo {
private val template = Foo(y="")
val Defaults = {
case X => template.x
}
}
object Test {
val x: Option[Int] = getX()
val y: Option[String] = getY()
Foo(
x=x.getOrElse(Foo.Defaults(X))
y=y.get
)
}
从安全角度来看,这是一个更好的类型,但现在我必须为每个默认参数创建一个类型。
正确而简洁的解决方案应该是什么样的?
【问题讨论】:
标签: scala case-class