16

由于发明者强调了Scala的类型安全性,我不理解对象(至少来自案例类)缺少 equals 方法,该方法仅允许检查具有相同类型的对象的相等性。我希望有一种方法===可以默认实现这种行为。当然,Java 互操作性需要有一个适用于Any类型的方法,但在许多情况下,我只想检查相同类型的对象之间的相等性。

为什么我需要它?

例如,我有两个案例类并从中创建对象

  case class Pos(x: Int, y: Int)
  case class Cube(pos: Pos)

  val startPos = new Pos(0, 0)
  val cubeOnStart = new Cube(startPos)

后来我需要检查几次位置,不小心写了

  if (startPos == cubeOnStart) {
    // this code will never be executed, but unfortunately this compiles
  }

但意味着

  if (startPos == cubeOnStart.pos) {
    // this code can be executed if positions are equal
  }

如果有一种方法===可用,我会凭直觉使用它。

缺少这种方法是否有充分的理由或解释?

4

2 回答 2

23

Scala 中的平等是一团糟,而您的为什么问题的答案(Stack Overflow 并不是真正的理想场所)是“因为语言设计者认为 Java 互操作性胜过在这种情况下做合理的事情”。

至少在最近版本的 Scala 中,您startPos == cubeOnStart会收到一条警告,指出比较这些不同类型的值“将始终产生错误”。

Scalaz通过类型安全的类型类提供===您正在寻找的运算符Equal。你会写这样的东西:

import scalaz._, Scalaz._

implicit val cubeEqual = Equal.equalA[Cube]
implicit val posEqual = Equal.equalA[Pos]

现在startPos === cubeOnStart不会编译(这正是我们想要的),但startPos === cubeOnStart.pos会,并且会返回true.

于 2013-11-02T14:27:40.217 回答
1

截至 2018 年,Dotty 存在多元平等。但是,它需要开发人员定义相等检查有意义的类型。总而言之,优雅的向后兼容解决方案。

于 2018-04-16T23:21:41.663 回答