case类中的var成员是否会影响case类的相等性?

时间:2013-01-15 23:54:44

标签: scala equality case-class algebraic-data-types

我在代码中大量使用了case类,回复了case类的底层相等定义,使其行为正确。然后我发现我需要将另一个字段成员添加到案例类中。

  1. 因此,如果我在案例类中添加var字段成员,是否会破坏案例类的相等属性?
  2. 如果1为是,那么如果我只更改var字段值一次,之后,在案例类进入任何集合或进行相等比较之前不会发生任何重新分配,那还会是平等行为?

2 个答案:

答案 0 :(得分:12)

案例类相等仅基于其主要构造函数属性,无论它们是var还是val(是的,您可以通过明确var来使它们var覆盖案例类构造函数args所拥有的隐含val。)在case class 的主体中添加属性不会影响编译器生成的equals(other: Any)方法

证人:

package rrs.scribble

object  CCVarEq
{
  case class CC1(i: Int, j: Float, var k: Double)

  case class CC2(i: Int, j: Float, var k: Double) {
    var l = math.Pi
  }

  def show {
    val cc11 = CC1(1, 2.0f, 3.0)
    val cc12 = CC1(1, 2.0f, 3.0)

    val cc21 = CC2(1, 2.0f, 3.0); cc21.l = math.E
    val cc22 = CC2(1, 2.0f, 3.0)

    printf("cc11 == cc12: %s%n", cc11 == cc12); cc12.k = math.Pi * math.E
    printf("cc11 == cc12: %s%n", cc11 == cc12)

    printf("cc21 == cc22: %s%n", cc21 == cc22)
  }
}

在REPL中:

scala> import rrs.scribble.CCVarEq._
import rrs.scribble.CCVarEq._

scala> show
cc11 == cc12: true
cc11 == cc12: false
cc21 == cc22: true

所有关于并发性的关键点也是有效的。

答案 1 :(得分:2)

这不是那么简单。您在一个线程上更新案例类var,另一个线程正在执行相等性检查。除非var是易失性的,否则在执行相等性检查之前,对var的更改不会传播到另一个线程是合理的。所以你可能有竞争条件。无论这种情况只发生过一次还是多次。

一旦未定义到该点,值是否会被更改?如果是这样,请使用懒惰的val。它有一个同步问题,可能会降低高性能代码,但否则会满足您的用例。