Scala:如何使用默认值初始化对象

时间:2012-05-06 17:44:31

标签: scala constructor default-value

我认为用例子

可以更好地解释这一点

我有以下案例类

case class Person(name: String = "no name", surname: String = "no surname")

我想创建一个通用函数来填充它,例如,json消息,可能没有指定所有字段

我知道要使用默认值,简单的答案不是将它们传递给构造函数,但如果我有几个字段可能会或可能不会出现在json中,我应该使用一个巨大的切换句子覆盖每一个缺失参数的可能组合。在这种情况下,在读完json之后,我应该注意名字&姓氏在场,没有姓名,没有姓,也没有姓名,也没有姓氏......(哎呀,我希望自己能说清楚)。

更确切地说,我正在尝试开发一个函数,允许我根据以下json值创建一个人,当缺少某些参数时使用默认值

{ "name": "john", "surname": "doe" }
{ "surname": "doe" }
{ "name": "john" }
{ }

这就是为什么我正在寻找一种更通用的方法来解决这个问题。

(我将展示一些伪代码,以便了解我想要实现的目标)

我在考虑类似的事情:

val p = Person(name= "new person name", surname= Unit)

在这种情况下,姓氏应该获得默认值

或类似

val p = Person( Map( "name" -> "new person name" ) _* )

因此它也采用了姓氏的默认值

或者也许在构造函数中执行它,如果我检测到空值(或None),我可以指定默认值。

事实上,我试图避免重复默认值的定义。

无论如何,实现这样的事情的最惯用的方法是什么?

2 个答案:

答案 0 :(得分:21)

如果您想使用默认值,通常只需要保留该命名参数:

scala> val p = Person(name = "new person name")
p: Person = Person(new person name,no surname)

但是,既然您想明确知道某个值是否应该默认,那么您可以在构造函数中实现基于Map的想法。如果您不想重复默认值,那么这两个选项如何:

选项1:默认值的外化常量

在外部设置默认值。在主构造函数和基于Map的构造函数中使用它们。

val nameDefault = "no name"
val surnameDefault = "no surname"

case class Person(name: String = nameDefault, surname: String = surnameDefault) {
  def this(m: Map[String, String]) =
    this(m.getOrElse("name", nameDefault), m.getOrElse("surname", surnameDefault))
}

用法:

new Person(name = "new person name", surname = "new person surname")
new Person(Map("name" -> "new person name"))
new Person(name = "new person name")

选项2:选择的备用构造函数

你可能会发现它更清洁,因为它不依赖于外化常量。这里唯一的缺点是,如果你只想用一些参数构造,你必须将每个参数包装在Some()中。

case class Person(name: String, surname: String) {
  def this(name: Option[String] = None, surname: Option[String] = None) =
    this(name.getOrElse("no name"), surname.getOrElse("no surname"))

  def this(m: Map[String, String]) = this(m.get("name"), m.get("surname"))
}

用法:

new Person(name = "new person name", surname = "new person surname")
new Person(Map("name" -> "new person name"))
new Person(name = Some("new person name"))
new Person(name = "new person name") // can't do this

答案 1 :(得分:0)

我认为这可能是Either的用例。您可以指定两种类型的Either。

val name: Eiter[String, Unit] = Left("name")
val surname: Either[String, Unit] = Right( () )

现在你可以检查你是左派还是右派,并用你想要的参数调用构造函数。