假设我有一个类似的案例类
case class Person(fname:String, lname:String, nickName:Option[String] = None)
Run Code Online (Sandbox Code Playgroud)
在创建像Person("John","Doe")这样的实例时,我希望将nickName自动分配给fname,如果没有给出.例如:
val p1 = Person("John", "Doe")
p1.nickName.get == "John"
val p2 = Person("Jane", "Doe", "Joe")
p2.nickName.get == "Joe"
Run Code Online (Sandbox Code Playgroud)
如何实现从另一个字段自动分配一个字段?
在repl中尝试以下解决方案.我认为这与repl有关
scala> case class Person(fname: String, lname:String, nickName:Option[String])
defined class Person
scala> object Person { def apply(fname:String, lname:String):Person = {Person(fname, lname, Some(fname))}}
console:9: error: too many arguments for method apply: (fname: String, lname: String)Person in object Person
object Person { def apply(fname:String, lname:String):Person = {Person(fname, lname, Some(fname))}}
Run Code Online (Sandbox Code Playgroud)
您可以重载案例类的构造函数
case class Foo(bar: Int, baz: Int) {
def this(bar: Int) = this(bar, 0)
}
new Foo(1, 2)
new Foo(1)
Run Code Online (Sandbox Code Playgroud)
因此,如果nickName为none,您可以检查案例.
您也可以以相同的方式重载它的apply方法.这样,你就可以使用了
Foo(1,2)
Foo(1)
Run Code Online (Sandbox Code Playgroud)
在当前的案例类定义中,您可以覆盖案例类的构造函数及其配套对象的apply方法,如Facundo Fabre的答案所述。
您将获得如下内容:
object Person {
def apply(fname:String, lname:String): Person = Person(fname, lname, fname)
}
case class Person(fname:String, lname:String, nickName: String) {
def this(fname:String, lname:String) = this(fname, lname, fname)
}
Run Code Online (Sandbox Code Playgroud)
这是技术上正确且非常巧妙的编码。但就我的口味而言,它有点聪明,因为它破坏了一个重要的属性:
CaseClass.unapply(CaseClass.apply(x1,x2,x3)) == (x1,x2,x3)
Run Code Online (Sandbox Code Playgroud)
换句话说:当我使用apply
带有一些参数元组的case类,然后使用unapply
我对其进行解构时,我希望得到放入的原始元组apply
(忽略currying和option type)。
但是在这种情况下,此属性不再成立:
Person.unapply(Person("John", "Smith"))
// result: Option[(String, String, String)] = Some((John,Smith,John))
Run Code Online (Sandbox Code Playgroud)
解构使用unapply
用于模式匹配(match{ case ... => ...
)。这是案例类的常见用例。
因此,尽管代码非常聪明,但可能会使其他人感到困惑,并破坏他们的代码所依赖的属性。
当需要过于聪明的代码时,通常最好重新考虑一下人们试图解决的问题。在这种情况下,我建议您区分用户选择的昵称和系统分配给用户的昵称。在这种情况下,我将只构建一个如下的case类:
case class NickedPerson(fname : String, lname : String, chosenNick : Option[String] = None) {
val nick = chosenNick.getOrElse(fname)
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以只使用该字段nick
来访问计算出的昵称,或者chosenNick
如果您想知道用户是否提供了该昵称,请使用:
NickedPerson("John", "Smith").nick
// result: String = "John"
NickedPerson("John", "Smith", Some("Agent")).nick
// result: String = "Agent"
Run Code Online (Sandbox Code Playgroud)
此案例不会更改有关案例类的基本属性。
归档时间: |
|
查看次数: |
1801 次 |
最近记录: |