Scala:如何使用默认值初始化对象 [英] Scala: how to initialize an object using default values

查看:2814
本文介绍了Scala:如何使用默认值初始化对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为这将更好地解释一个例子



我有以下案例类

  case类Person(name:String =no name,surname:String =no surname)

而我想要一个一般的函数来填充它,例如,一个json消息,可能不指定所有字段



我知道,使用默认值简单的答案是不将它们传递给构造函数,但如果我有几个字段可能或可能不会出现在json,我应该使用一个巨大的切换句覆盖每个可能的组合缺少参数。在这种情况下,在阅读json后,我应该照顾名字&姓氏,姓氏,姓氏,姓氏,姓氏,情况...(哎,我希望我明白了)。



m尝试开发一个函数,允许我从下面的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),我可以分配默认值。



事实上,重复默认值的定义。



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

解决方案

如果你想使用默认值,通常只需要抛弃该参数:

  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类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类Person(name:String,surname:String){
def this(name:Option [String] = None,surname:Option [String ] = None bbb
这个(m:Map [String,String] )= this(m.get(name),m.get(surname))
}


b $ b

用法:

  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)//不能这样做


I think this will be better explained with an example

I have the following case class

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

And I want to make a general function to populate it from, for example, a json message, that might not specify all fields

I know that to use the default values the simple answer is not to pass them to the constructor, but if I have several fields that may or may not appear in the json, I should have to use a huge switch sentence covering every possible combination of missing parameters. In this case, after reading the json, I should take care of name & surname present, no name, no surname and no name nor surname case... (Gee, I hope I made myself clear).

To be more precise, I'm trying to develop a function that allows me to create a person from the followgin json values, using the default values when there's some parameter missing

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

That's why I'm looking for a more general way to handle this.

(I'll show some pseudo code to give and idea of what I'm trying to achieve)

I was thinking about something like:

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

And in that case surname should get the default value

Or something like

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

So that it also takes the default value for surname

Or maybe doing it in the constructor, if I detect a null value (or None) I could assign the default value.

In fact, I'm trying to avoid repeating the definition of the default values.

Anyway, what would be the most idiomatic way to achieve such a thing?

解决方案

If you want the default value to be used, you normally just leave off that named argument:

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

But, since you want to explicitly know whether a value should be defaulted or not, you could implement your Map-based idea in a constructor. If you don't want to repeat the defaults, how about these two options:

Option 1: Externalized constants for defaults

Set the defaults externally. Use them in both the main constructor and the Map-based constructor.

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))
}

Usage:

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

Option 2: Optionified alternate constructor

You may find this a little cleaner since it doesn't rely on externalized constants. The only downside here is that if you want to construct with only some of the parameters, you have to wrap each one in 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"))
}

Usage:

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

这篇关于Scala:如何使用默认值初始化对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆