如何更改案例类的基类属性

时间:2019-01-16 17:22:01

标签: scala

采用以下代码:

class A(val i: Int)

case class B(str: String) extends A(1)

val b = B("test")

在我的场景中,我受B定义的限制,不能更改。我也希望避免重构B,因为我有许多这样的对象,它们的属性比本例中的要多。

有什么方法可以创建b的新副本(使用反射还是其他方式),并为i赋一个新值?

等同于:

val b2 = b.copy(i = 2)

注意:问题是可以做到吗?并不是最佳的编程实践。

3 个答案:

答案 0 :(得分:1)

您可以使用反射来完成此操作:

  val b = B("foo")
  val c = b.copy()
  println(b.i) // prints 1
  val field = classOf[A].getDeclaredFields.head
  field.setAccessible(true)
  field.setInt(c, 2)
  println(c.i) // prints 2

但是请注意,这不仅是“不良的编程习惯”,而且是完全破坏合同

您的声明case class B(s: Sting) extends A(1)保证B所有实例将始终i等于1,这是一个谎言。

更不用说,有趣的事实,例如b == ctruec.copy.i为1等。 不要这样

答案 1 :(得分:0)

如果您以这种方式定义B,则不会。但是这段代码对我有用:

class A(val i: Int)

case class B(str: String, override val i:Int=1) extends A(i)

val b = B("test")
val b2 = b.copy(i = 2)  

P.S。从技术上讲,您可以不做任何修改就直接复制,然后使用反射来编辑i,但这不是个好主意。

答案 2 :(得分:0)

您可以这样做:

val b2 = new B(b.str) { override val i = 2 }

不利之处在于,您必须根据大量参数来重新构建B