2016-11-23 2 views
0

質問1リストとセット(異なる要素)を比較すると、なぜこのコードがtrueを返しますが、ListをListまたはSetと比較するとfalseを返します。一覧でおそらくcanEqualcanEqual in Listは、Set引数で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 

は、インスタンスのリストタイプではなく、いくつかのスーパークラスのインスタンスまたはおそらくdoesntのオーバーライド等しいかどうかをチェックしません。これは本当ですか?

質問2 - canEqualsは、インスタンスが他のインスタンスと等しいかどうかを定義するためにequalsおよびhashcodeと共に使用されています。 canEqualsは一般的にequalsによって呼び出されます。ユーザーがコードから直接canEqualを呼び出すときにユースケースがありますか(上記のようにしようとしていますか?)

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

だから、すべてはデフォルトで等しくすることができる - しかし、それが可能になることを意味するものではありません:

答えて

5

のは、単純な例を見てみましょう。非最終クラスのための

canEqual方法:canEqualの本当のユースケースは、等価性を(this articleを参照)を無効にしています。これにより、サブクラスが親クラス のクラスまたは兄弟クラスと等しくないようにする場合は、サブクラスを canEqualに上書きできます。

したがって、canEqualの全理由は継承です(兄弟/親では等価性が完全に無効になります)。それはequalsの外でそれを上記の記事で述べたLiskov Substitution Principleに違反して呼び出すことは推奨されません。

IMHO、私はまったく使用することをお勧めしませんが、直感的でわかりやすく、dangerousです。エンティティ間の平等を無効にする必要がある場合は、継承が論理的には等価の継承を必要とするため、継承を優先する方が良いですが、構成は柔軟性があります。

関連する問題