【问题标题】:Why has Scala no type-safe equals method?为什么 Scala 没有类型安全的 equals 方法?
【发布时间】:2013-11-13 14:01:36
【问题描述】:

由于发明者强调 Scala 的类型安全性,我不理解允许对象(至少来自 case 类)缺少 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
  }

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

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

【问题讨论】:

标签: scala equals equality


【解决方案1】:

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

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

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

import scalaz._, Scalaz._

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

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

【讨论】:

  • 可以说,Java 互操作总的来说是合理的,因为它大大增加了可用库的大小和范围。这是实用语言的一个重要考虑因素……
  • 感谢您的解决方案。我知道对于 Java 互操作性,带有参数 Any 的 equals 方法是存在的,但是缺少类型安全的变体似乎是语言/库中的一个很大差距。
  • 这是 Martin Odersky 的 considered
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    相关资源
    最近更新 更多