簡體   English   中英

Scala:如何覆蓋任意元素類型的元組 equals() 方法?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM