具体 class(或情况 class)的 equals/hashCode 中的 'parent' 字段存在问题,它扩展了乘法特征(具有具体字段)

Troubles with 'parent' fields in equals/hashCode of concrete class(or case class) which extends a multiply traits(with concrete fields)

我是 Scala 的新手,对特征混合感到困惑。我正在使用多个特征来存储一些字段组并将它们与具体 class.

混合

全局问题是关于 equals 和 hashCode 方法将如何操作这些字段(特征中的字段可以有默认值)。

实际上我不打算拥有一堆构造函数并再次定义所有这些字段。我的 class 可以有很多字段组合,我想使用构建器模式或简单的修改器链接。 我不明白如何在我的equals和具体class的hashCode中操作来自不同特征的字段(我只能用它们硬编码逻辑,但不能使用'super.equals()')。 Traits 不能有自己的 equals/hashCode 方法,或者我在某些时候弄错了?

示例:

trait Task {  

  var name: Option[String] = None

  var comment: Option[String] = None

  ... // plenty other fields

}

trait Budget {

  var price: Option[Long] = None

}

class Event extends Task with Budget {

  var place: Option[String] = None

  ... // plenty other fields

}

当使用 case classes 时 - 生成的 equals/hashCode/toString 不操作父字段(来自特征的字段)

为什么不呢。 您可以轻松 override equalshashCode 任何您喜欢的特征。

trait PP {
  override def hashCode(): Int = 1

  override def equals(obj: scala.Any): Boolean = true
}

class BB(val z: Int) extends PP {
  override def hashCode(): Int = super.hashCode()

  override def equals(obj: Any): Boolean = super.equals(obj) && (obj match {
    case b: BB => b.z == z
    case _ => false
  })
}

绝对你应该非常小心 hashCode 和 equals 在这些特征中的实现(同时进行类型检查:obj.isInstanceOf[otherTrait])以遵循这些方法的约定。

--

证明所有 equals 都被调用的示例。

scala> :paste
// Entering paste mode (ctrl-D to finish)

  trait T1 {
    override def equals(obj: scala.Any): Boolean = {
      println("T1 invoked")
      super.equals(obj)
    }
  }

  trait T2 {
    override def equals(obj: scala.Any): Boolean = {
      println("T2 invoked")
      super.equals(obj)
    }
  }
  trait T3 extends T1 {
    override def equals(obj: scala.Any): Boolean = {
      println("T3 invoked")
      super.equals(obj)
    }
  }
  class C1 extends T1 with T2 with T3 {
    override def equals(obj: scala.Any): Boolean = {
      println("C1 invoked")
      super.equals(obj)
    }
  }

  new C1().equals(new C1())

// Exiting paste mode, now interpreting.

C1 invoked
T3 invoked
T2 invoked
T1 invoked
defined trait T1
defined trait T2
defined trait T3
defined class C1
res7: Boolean = false

scala>

scala>