【发布时间】:2015-10-11 09:56:01
【问题描述】:
阅读 Martin 的书,关于平等 Object equality chapter 的一章可能会注意到,在 scala 中正确实现 equals(实际上在任何其他语言中)并不是很简单。然而 scala 非常强大和敏捷,我不敢相信它不能简化一些事情。我知道 scala 会为案例类生成正确的equals,所以我想知道为什么它不能为普通类生成简化?
为了说明我的观点,我写了一个例子来说明我会如何看待它。它可能有缺陷,我不得不使用ClassTag,由于性能原因,我知道这对于equals 这样的基本事物是非常错误的(任何提示,如果没有ClassTag,我怎么能做到这一点?),但认为scala 可以为案例类生成正确的equals,我想说它应该能够为普通类生成正确的代码,让开发人员提供应该用于比较对象的Key。
trait Equality[T] extends Equals {
val ttag: ClassTag[T]
def Key: Seq[Any]
def canEqual(other: Any): Boolean = other match {
case that: Equality[_] if that.ttag == ttag => true
case _ => false
}
override def equals(other: Any): Boolean =
other match {
case that: Equality[T] => canEqual(that) && Key == that.Key
case _ => false
}
override def hashCode = Key.foldLeft(1)((x, y) => 41 * x + y.hashCode)
}
那么你可以这样使用它:
class Point(val x: Int, val y: Int)(implicit val ttag: ClassTag[Point]) extends Equality[Point]{
override def Key: Seq[Any] = Seq(x, y)
}
我不太喜欢ClassTags,所以我可能弄错了,但它似乎有效。但这不是我要问的 - 我想知道是否有任何严重的原因,为什么 scala 本身不简化实现相等检查?
【问题讨论】:
-
可能有很多方法。像scalaz.Equal 这样的一些可以满足类型安全的需求。有些人喜欢你的简单和狭窄的使用。没有黄金标准,所以它不在图书馆里。
-
@Odomontois 我知道,但是当我读这本书时,听起来
canEqual的方法应该涵盖 99% 的情况,我大多同意这一点。我希望 scala 具有这样的默认行为,对于最后 1%,我仍然能够覆盖equals、hashCode和现在canEqual,所以我不明白为什么我们没有任何好的默认值行为
标签: scala