我是Scala的新手并且对混合特征感到困惑。我使用多个特征来存储一些字段并将它们与具体类混合。
全局问题是关于equals和hashCode方法如何操作这些字段(traits中的字段可以具有默认值)。
实际上,我并没有计划拥有一堆协处理器并再次定义所有这些字段。我的班级可以有很多字段组合,我想使用Builder模式或简单的mutators链接。 我不明白如何在我的equals和具体类的hashCode中操作来自不同特征的字段(我只能用它们硬编码逻辑,但不能使用' super.equals()')。特征不能有自己的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类时 - 生成的equals / hashCode / toString不运行父字段(traits中的字段)
答案 0 :(得分:3)
为什么不呢。
您可以轻松地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并在这些特征中等于实现(同时进行类型检查: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>