问题1 - 当我将List与Set(不同元素)进行比较时,为什么此代码返回true,但当我将List与List或Set进行比较时返回false?
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可能不会检查实例List类型但是某些超类实例或者可能不会覆盖equals。是这种情况吗?
问题2 - 我读到canEquals与equals和hashcode一起使用来定义一个实例是否等于某个其他实例。 canEquals通常由equals调用。当用户直接从代码调用canEqual时,是否有用例(就像我上面尝试的那样)?
答案 0 :(得分:5)
让我们从更简单的例子开始:
scala> "aaaa".canEqual(5)
res0: Boolean = true
所以默认情况下一切都是平等的 - 但它并不意味着它会是平等的。 canEqual
的实际用例是禁用等效性(请参阅this article):
非最终类的canEqual方法。这允许子类 如果他们想要不允许等于父级,则覆盖canEqual 班级或兄弟班。
因此canEqual
的全部原因是继承(在兄弟姐妹/父母中严格禁用相等)。建议不要在equals
之外调用它,因为它违反了上面文章中所述的Liskov替换原则。