为什么Scala案例类复制方法仅使用case类中定义的变量进行参数化?

时间:2018-03-01 15:16:13

标签: scala

为什么Scala案例类复制方法仅使用案例类中定义的变量进行参数化?

基于Q& A的问题:

Case class copy does not maintain state of an inherited trait

简短摘要 - 当使用字段定义trait并使用case类扩展时,case类上的copy将仅使用case类中定义的变量创建新的类实例,而不使用扩展特征。 / p>

 trait A {
    var list: List[Int] = List()

    def add(element: Int) = {
      list = element :: list
    }
  }

  case class B(str: String) extends A {
    val b = B("foo")
    println("B1: " + b.list)

    b.add(1)
    b.add(2)
    b.add(3)
    println("B2: " + b.list)

    val b2 = b.copy(str = "bar")
    println("B3: " + b.list)
    println("B4: " + b2.list)
  }

此处,B4: ()将为空,而B3:(3,2,1)

2 个答案:

答案 0 :(得分:2)

因为没有合理的方法可以始终如一地做你想做的事。

对于您的示例,copy的生成代码可能是

def copy(str: String = this.str, list: List[Int] = this.list): B = {
  val newB = B(str)
  newB.list = list
  newB
}

足够好。现在,如果您将list更改为私有,或val而不是var,会发生什么?在这两种情况下newB.list = ...都不会编译,编译器应生成什么代码?

答案 1 :(得分:0)

如果你真的想在复制后保留list的值(考虑到我在OP的评论中提到的可变性问题),你可以编写自己的copy方法。

case class B(str: String) extends A {
  def copy(str: String = this.str, list: List[Int] = this.list): B = {
    val newB = B(str)
    list.reverse.foreach(newB.add)
    newB
  }
}