实例化具有要为其成员设置的值的案例类

时间:2013-03-06 13:10:02

标签: scala case-class

考虑这个案例类

case class sample(val s: String = { /*compiled code*/ })
{
  val name:String = { /*compiled code*/ }
  val no:Int = { /*compiled code*/ }
}

我需要创建此类的实例,并将特定值设置为name和no。 但是我不能使用扩展这个类的另一个类。我必须传递相同的类实例。

2 个答案:

答案 0 :(得分:2)

你的意思是有人遇到了确保nameno被设置为特定方式且无法更改的麻烦,并且你想让它们包含其他内容,这可能会违反所有种类假设?这不是一个好主意,JVM会阻止你做一些如此愚蠢的事情(除非涉及到所有内容的自定义类加载器的荒谬困难技巧)。

如果你只是想想要设置那些val,但通常不必在构造函数中担心它们,那么有各种各样的解决方案。一种方法是使用lazy vals和私有变量来设置setter:

case class C(val s: String = "fish") {
  private var myN: Option[Int] = None
  def initializeN(n0: Int) {
    myN = Some(n0)
    if (n != n0) throw new Exception("Already initialized")
  }
  lazy val n: Int = myN.getOrElse(s.length)   // s.length is your code block
}

其中的作用如下:

scala> C("salmon")
res0: C = C(salmon)

scala> res0.initializeN(2); res0.n
res1: Int = 2

scala> C("herring")
res1: C = C(herring)

scala> res1.n
res2: Int = 5

scala> res1.initializeN(2)
java.lang.Exception: Already initialized
    at C.initializeN(<console>:11)
        ...

如果您想要初始化的编译时安全性,还可以使用其他各种技巧。以后的参数块可以引用之前的参数块,并且不会显示为匹配参数:

case class D(val s: String = "fish")(val n: Int = s.length) {}

您可以重载构造函数:

case class E(val s: String, n: Int) {
  def this(s: String) = this(s, s.length)
  def this() = this("fish")
}

以及上述的各种混合物也是可能的。

答案 1 :(得分:1)

使nameno构造函数参数不是一个选项吗?

case class Sample(s: String = { /*compiled code*/ },
                  name: String = { /*compiled code*/ },
                  no: Int = { /*compiled code*/ })

我假设/* compiled code */确定了字段的默认值。您可以按如下方式使用代码:

Sample()                   // all default values
Sample("some value for s") // default values for name and no
Sample("s", "name", 123)   // explicit values, no defaults