[英]Scala: How to override tuple equals() method for arbitrary element types?
我有一张地图,其中的值以元组为键。 在我的情况下,无论元素顺序如何,我都需要元组匹配,因此,例如,我需要保持:
(1, 2) == (2, 1) is true
如何覆盖元组equals
运算符,因此对于任何类型 X, Y :
(a:X, b:Y) == (b:Y, a:X) is true ?
稍后更正:另一个想法是编写我自己的具有所需行为的Pair
类。 在这种情况下, equals()
覆盖会是什么样子?
当然,您真的不想更改元组的语义,因为宇宙会内爆。 你只是想是这样的元组-除了他们平等的语义。
为什么不只使用案例类? 元组实际上只是现成的类,当定义一个类不值得麻烦时,它可以将一些东西放在一起。 好吧,如果你想改变平等,我会说这是值得的! 此外,您可以使用比 _1 和 _2 更有意义的名称。
当然,我不知道这些名字是什么,但这里有一些代码。 正如 Travis 指出的那样,处理相等性很棘手,部分原因是您还必须考虑哈希码。 希望这是合理的:
scala> case class Foo[T]( a:T, b:T ) {
override def equals( that:Any ) = that match {
case that:Foo[T] => ( that canEqual this ) && (
this.a == that.a && this.b == that.b ||
this.a == that.b && this.b == that.a
)
case _ => false
}
override def canEqual( that:Any ) = that.isInstanceOf[Foo[T]]
override def hashCode = a.hashCode + b.hashCode
}
defined class Foo
scala> Foo(1,2) == Foo(1,2)
res15: Boolean = true
scala> Foo(1,2) == Foo(2,1)
res16: Boolean = true
scala> Foo(1,2) == Foo(2,2)
res17: Boolean = false
scala> collection.immutable.HashSet( Foo(0,1), Foo(1,0), Foo(1,2) )
res18: scala.collection.immutable.HashSet[Foo[Int]] = Set(Foo(0,1), Foo(1,2))
请注意,由于相等的定义, res18
包含Foo(1,0)
但不包含Foo(1,0)
Foo(0,1)
。
好吧,您不能覆盖为Tuple2
定义的行为。 毕竟,这两个元组不相等,因此您不能告诉 Scala 说它们相等。
您可以定义您自己的具有您想要的相等属性的元组类型,但是您将无法使用漂亮的括号语法。
最简单的方法是定义您自己调用的相等函数:
def myEquals[X,Y](a: (X,Y), b: (Y,X)) = a._1 == b._2 && a._2 == b._1
那么你有:
scala> myEquals((1,'a'), ('a',1))
res0: Boolean = true
您还可以为 Tuple2 定义一个新的相等运算符
implicit class NewEqualityTuple2[X,Y](a: (X,Y)) {
def =<>=(b: (Y,X)) = a._1 == b._2 && a._2 == b._1
}
给这个:
scala> (1,'a') =<>= ('a',1)
res1: Boolean = true
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.