具体 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
equals
和 hashCode
任何您喜欢的特征。
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>
我是 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
equals
和 hashCode
任何您喜欢的特征。
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>