[英]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.