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

问题描述 投票:0回答:2

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

基于问答的问题:

Case class copy does not maintain state of an inherited trait

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

 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)

scala
2个回答
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 = ...都不会编译,那么编译器应该生成什么代码?


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
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.