2016-11-23 38 views
0

問題1 - 爲什麼當我比較List和Set(不同元素)時,此代碼返回true,但當List與List或Set比較時返回false?列表中的canEqual爲設置參數返回true

scala> val l = List(1,2,3) 
l: List[Int] = List(1, 2, 3) 

scala> val l2=List(1,2,3) 
l2: List[Int] = List(1, 2, 3) 

scala> val l3=List(1,3,3) 
l3: List[Int] = List(1, 3, 3) 

scala> l.canEqual(l2) 
res2: Boolean = true 

/*I guess this returns true becuase canEqual check for type of the passed instance. Something like def canEqual(other: Any): Boolean = other.isInstanceOf[List] */ 

scala> l.canEqual(l3) 
res3: Boolean = true 

//but if canEqual checks for type of passed instance then why this returns true when I call canEqual on List but pass a Set 

scala> val s = Set(1,2,3) 
s: scala.collection.immutable.Set[Int] = Set(1, 2, 3) 

scala> l.canEqual(s) 
res4: Boolean = true 

scala> val s2=Set(2,3,4) 
s2: scala.collection.immutable.Set[Int] = Set(2, 3, 4) 

scala> l.canEqual(s) 
res5: Boolean = true 

scala> l.canEqual(s2) 
res6: Boolean = true 

大概canEqual在列表中不檢查的實例列表類型,但一些超類的實例或可能犯規覆蓋equals方法。是這樣嗎?

問題2 - 我讀了canEquals與equals和hashcode一起使用來定義一個實例是否等於某個其他實例。 canEquals通常由equals來調用。當用戶直接從代碼中調用canEqual時,是否有用例(如我正在嘗試做的那樣)?

回答

5

讓我們先從簡單的例子:

scala> "aaaa".canEqual(5) 
res0: Boolean = true 

所以一切都可以在默認情況下等於 - 但並不意味着它會。的canEqual真正使用情況禁用等價(見this article):

canEqual方法對非最終的類。這允許子類 覆蓋canEqual,如果他們不希望等於父類 類或兄弟類。

因此,canEqual的全部原因是繼承(謹慎地禁止兄弟姐妹/父母的平等)。不建議將其稱爲equals以外,因爲它違反了上面文章中所述的Liskov替換原則。

恕我直言,我不會推薦使用,這是違反直覺和dangerous。如果您需要禁用實體之間的平等,最好將組合繼承,因爲繼承在邏輯上需要繼承平等,但組合更靈活。

相關問題