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

问题描述 投票:14回答:2

我想用一个例子可以更好地解释这一点

我有以下案例类

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" ) _* )

因此它也采用了surname的默认值

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

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

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

scala constructor default-value
2个回答
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

0
投票

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

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

现在,您可以检查是左侧还是右侧,并使用所需的参数调用构造函数。

© www.soinside.com 2019 - 2024. All rights reserved.