如果用户不提供name参数,我试图提供合理的默认值。在Eclipse IDE的Scala工作表中执行以下操作会生成编译器错误:
case class Type(id: Int, name: String, description: String = "")
case class Definition(id: Int, types: List[Type], separator: String = ";", name: String = types.mkString(separator))
错误是“找不到:值分隔符”,在列表的mkString方法调用内的标识符“separator”上指示。由于这是一个案例类,并且之前的参数已经定义,为什么我不能在定义name的默认值时使用“separator”。事实证明,我甚至无法使用“类型”来定义“名称”的默认值。
我试图解决这个问题,但我没有看到如何不将名称变成var,这不是我想做的事情。对此有任何指导或理解。
更新: 好吧,我发现解决这个问题的方法是使用伴侣对象转发到构造函数:
case class Type(id: Int, name: String, description: String = "")
object Definition {
def create(id: Int, types: List[Type], separator: String = ";", name: String = "") =
Definition(id, types, separator, if (name != "") name else types.map(_.name).mkString(separator))
}
case class Definition(id: Int, types: List[Type], separator: String = ";", name: String) {
require(!separator.isEmpty, "separator must not be empty")
require(!name.isEmpty, "name must not be empty")
}
与我最初尝试的相比,这确实是一个类似Java的样板。还有其他/更好的方法吗?
答案 0 :(得分:3)
在Definition的构造函数中,参数不能引用其他参数:
scala> case class Foo(x: Int, y: Int = x + 1)
<console>:7: error: not found: value x
case class Foo(x: Int, y: Int = x + 1)
^
你也不能讨论构造函数的参数,虽然它看起来像是有效的:
scala> case class Foo(x: Int)(y: Int = x + 1)
defined class Foo
scala> val test = Foo(3)()
test: Foo = Foo(3)
scala> test.y
<console>:11: error: value y is not a member of Foo
test.y
^
通过在定义的伴随对象中定义额外的apply方法,我能够达到你想要的效果:
case class Type(id: Int, name: String, description: String = "")
case class Definition(id: Int, types: List[Type], separator: String, name: String)
object Definition {
def apply(id: Int, types: List[Type], separator: String): Definition = Definition(id, types, separator, types.mkString(separator))
def apply(id: Int, types: List[Type]): Definition = Definition(id, types, ";")
}
因为这些是常规方法,而不是构造函数,所以它们可以根据方法体中的需要引用和操作它们的参数。例如:
// Entering paste mode (ctrl-D to finish)
val type1 = Type(1, "foo")
val type2 = Type(2, "bar", "not baz")
val myDef = Definition(1, List(type1, type2))
// Exiting paste mode, now interpreting.
type1: Type = Type(1,foo,)
type2: Type = Type(2,bar,not baz)
myDef: Definition = Definition(1,List(Type(1,foo,), Type(2,bar,not baz)),;,Type(1,foo,);Type(2,bar,not baz))
答案 1 :(得分:2)
只需将name
放入新参数列表中即可解决此问题。后续参数列表中的参数可以引用先前列表中的参数值,也可以从中推断出类型。
case class Definition(id: Int, types: List[Type], separator: String = ";")(name_ : String = types.mkString(separator)) {
def name = name_
}
答案 2 :(得分:0)
你可能想要的是这样的:
case class Type(id: Int, name: String, description: String = "")
case class Definition(id: Int, types: List[Type], separator:String, name: String)
object Definition{
def apply(id: Int, types: List[Type], separator: String = ";") : Definition =
Definition(id,types,separator,types.mkString(separator))
}
这类似于Shadowlands的解决方案。