我可以自定义案例类中的值组件吗?

时间:2016-04-05 16:22:31

标签: scala constructor case-class

说我在库中有一些案例类:

case class MyClass(a: Int, b: Int)

后来事实证明我的库中存在一个错误,我需要在其中一个参数上应用一些额外的逻辑来保持工作正常,这样就可以从用户的透视实例中实现:

val x = MyClass(1, 2)
println(x.a)  // prints '3' or whatever I happen to compute for 'a'

换句话说,x.a的最终值不一定是传递给构造函数的值。我知道这看起来很疯狂,但相信我,我需要它。在大多数情况下,x.a仍将返回传递给构造函数的内容,但构造函数参数有一个值会导致错误,我需要对其进行转换。

我看到两种方法来实现这一目标。我可以a var

case class MyClass(var a: Int, b: Int) {
  a = someComputation()
}

然后该类变得可变,因为a可以从外部设置。如果我可以移除或隐藏'我的问题将得到解决。生成的setter但它似乎不可能。如果我添加

private def a_=(newA: Int) {}

它不会覆盖var生成的setter,因此它会看到两个方法定义并且不会编译。

第二个选项是创建一个与构造函数参数分开的字段/方法:

case class MyClass(private val _a: Int, b: Int) {
  val a = someComputation(a)
}

_a用于所有特殊生成的方法,例如equalstoString等,而自定义字段a则不具备。< / p>

有没有办法转换构造函数参数而不影响API的其余部分?

2 个答案:

答案 0 :(得分:2)

我要做的是覆盖随播对象上的apply方法,以便通过正确的计算创建MyClass的实例。

object MyClass {
   def apply(a: Int, b: Int) = new MyClass(someComputation(a),b))
}

然后您可以将其称为val x = MyClass(1, 2),但如果您仍希望进行计算,则无法像val x = new MyClass(1, 2)一样调用它。

显然以上所有内容都不能在REPL之外工作。

相反,我会选择同伴对象的另一种方法,它不是一个很好的解决方案,但它应该有效:

object MyClass {
   def create(a: Int, b: Int) = new MyClass(someComputation(a),b))
}

答案 1 :(得分:-2)

那么,你想要MyClass(a=1).a == 2之类的东西返回true吗? 你真的需要解释为什么这是一个坏主意? ;)

感谢上帝,这是不可能的!