为什么scala副本不保留原始类实例的状态?

为什么scala副本不保留原始类实例的状态?,scala,Scala,似乎copy不保留原始实例的任何状态,而只是使用基类定义使用新值创建新实例。有人知道为什么要这样实施吗 scala> case class A(){ var y = 2 } defined class A scala> val a = new A() a: A = A() scala> a.y = 9 a.y: Int = 9 scala> a.y res9: Int = 9 scala> val b = a.copy() b: A = A() scala

似乎copy不保留原始实例的任何状态,而只是使用基类定义使用新值创建新实例。有人知道为什么要这样实施吗

scala> case class A(){ var y = 2 }
defined class A

scala> val a = new A()
a: A = A()

scala> a.y = 9
a.y: Int = 9

scala> a.y
res9: Int = 9

scala> val b = a.copy()
b: A = A()

scala> b.y
res10: Int = 2

这不是对您的问题的直接回答,但这是如何以惯用的Scala方式实现您想要的

final case class A(a: Int = 2) // if a is not provided it will fallback to the default value of 2
val a = A(a = 3) // A(3)
val b = a.copy(a = 9) // A(9) - BTW, this is the same as A(a = 9)

case类用于对不可变数据对象建模,当您想要创建与另一个对象共享公共状态的新对象时,copy方法作为快捷方式提供,因此您只需要定义要更改的数据片段。

不是对您的问题的直接回答,但这就是如何以一种惯用的Scala方式实现您想要的

final case class A(a: Int = 2) // if a is not provided it will fallback to the default value of 2
val a = A(a = 3) // A(3)
val b = a.copy(a = 9) // A(9) - BTW, this is the same as A(a = 9)

case类用于建模不可变的数据对象,当您想要创建与另一个对象共享公共状态的新对象时,copy方法作为一种快捷方式提供,因此您只需要定义要更改的数据片段。

这既不是错误,也不是易变性问题

case类的工作方式是,它的所有特性equals、hashcode、toString、copy等都依赖于它的构造函数参数,其中一些不适用于curry

虽然变量是val,但您也会遇到同样的问题。例如

case class AAA() {
  val field = 1
}

val instanceA = new AAA() {
  override val field: Int = 5
}

println(instanceA.field)
// 5

println(instanceA.copy().field)
// 1
你的案例课应该是

case class A(y:Int = 2)

这既不是bug,也不是易变性问题

case类的工作方式是,它的所有特性equals、hashcode、toString、copy等都依赖于它的构造函数参数,其中一些不适用于curry

虽然变量是val,但您也会遇到同样的问题。例如

case class AAA() {
  val field = 1
}

val instanceA = new AAA() {
  override val field: Int = 5
}

println(instanceA.field)
// 5

println(instanceA.copy().field)
// 1
你的案例课应该是

case class A(y:Int = 2)
有人知道为什么要这样实施吗

scala> case class A(){ var y = 2 }
defined class A

scala> val a = new A()
a: A = A()

scala> a.y = 9
a.y: Int = 9

scala> a.y
res9: Int = 9

scala> val b = a.copy()
b: A = A()

scala> b.y
res10: Int = 2
这个Scala语言很好地解释了为什么它是以这种方式实现的。特别是,丹尼尔·索布拉尔的例子非常有意义:

假设一个变量应该包含一个唯一的数字,这样 实例数是否相同?或者假设它指向一个可变的 对象-是应该在实例之间共享,还是复制以便 每个实例都有它自己的实例

有人知道为什么要这样实施吗

scala> case class A(){ var y = 2 }
defined class A

scala> val a = new A()
a: A = A()

scala> a.y = 9
a.y: Int = 9

scala> a.y
res9: Int = 9

scala> val b = a.copy()
b: A = A()

scala> b.y
res10: Int = 2
这个Scala语言很好地解释了为什么它是以这种方式实现的。特别是,丹尼尔·索布拉尔的例子非常有意义:

假设一个变量应该包含一个唯一的数字,这样 实例数是否相同?或者假设它指向一个可变的 对象-是应该在实例之间共享,还是复制以便 每个实例都有它自己的实例


您好@azuras,case类在任何意义上都不是可变的,这就是为什么只复制构造函数参数的原因,因为它不是真正复制对象,而是创建一个新的对象,并对实际对象进行给定的修改。@LuisMiguelMejíaSuárez这算是scala错误吗?它允许您添加变量,然后假设您没有使用它们copy@JoelBerkeley我不会把它叫做虫子。Scala无论好坏都具有灵活性的特点。您可以在case类中使用vars,即使这被认为是一种不好的做法。LuisMiguelMeíaSuárez说了什么,然后很明显,为了获得您想要的行为,可以声明case类Avar y:Int=2。@JoelBerkeley:Scala语言规范非常清楚地说明了复制只会转发给构造函数。因此,copy不可能复制任何不属于构造函数的内容。类似地,SLS还明确指出,几乎所有的case类魔法都只适用于case类的元素,规范将其定义为构造函数参数,而没有其他定义。这也是我所见过的任何Scala课程中案例类的教学方式,也是我所见过的任何Scala书籍或教程中案例类的记录方式。嗨@azuras,案例类在任何意义上都不是可变的,这就是为什么复制只能回退到构造函数参数,因为它不是真正复制对象,但是创建一个新的,并对实际情况进行给定的修改。@LuisMiguelMejíaSuárez这算是scala bug吗?它允许您添加变量,然后假设您没有使用它们copy@JoelBerkeley我不会把它叫做虫子。Scala无论好坏都具有灵活性的特点。您可以在case类中使用vars,即使这被认为是一种不好的做法。LuisMiguelMeíaSuárez说了什么,然后很明显,为了获得您想要的行为,可以声明case类Avar y:Int=2。@JoelBerkeley:Scala语言规范非常清楚地说明了复制只会转发给构造函数。因此,copy不可能复制任何不属于构造函数的内容。类似地,SLS还明确指出,几乎所有的case类魔法都只适用于case类的元素,规范将其定义为构造函数参数,而没有其他定义。这也是我在Scala课程中教授案例课的方式 以及它们是如何记录在我所见过的任何Scala书籍或教程中的。