首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何说服Scala.js使用Javascript定义的方法equals进行比较?

如何说服Scala.js使用Javascript定义的方法equals进行比较?
EN

Stack Overflow用户
提问于 2018-10-03 18:43:36
回答 1查看 68关注 0票数 2

背景:真实的项目使用带有的。Three.js和facade都为许多类型定义了equals方法,包括Vector3__。这是一个演示equals功能的小示例。

我有一个Javascript类型,它定义了一个equals方法:

MyType.js:

代码语言:javascript
复制
function MyType(x, y) {
    this.x = x;
    this.y = y;
}

MyType.prototype.constructor = MyType;
MyType.prototype.equals = function(that) {
    return (this.x === that.x) && (this.y === that.y);
};

MyType.prototype.toString = function() {
    return "MyType(" + this.x + "," + this.y + ")";
};

MyType.scala外观:

代码语言:javascript
复制
@js.native
@JSGlobal("MyType")
class MyType(var x: Double, var y: Double) extends js.Any {
  def equals(that: MyType): Boolean = js.native

  override def toString: String = js.native
}

问题是Scala.js似乎提供了自己的equals实现,为了比较的目的,它隐藏了Javascript类提供的实现。

在我的测试套件中,我有以下代码:

代码语言:javascript
复制
class MyTypeTest extends FunSuite {
  test("Basic test") {
    val my0 = new MyType(0, 0)
    val my1 = new MyType(0, 0)
    val e1 = my0 equals my1
    val e3 = my0 == my1
    val e4 = my0 === my1
    assert(e1, "equals")
    assert(e3, "==")
    assert(e4, "===")
  }
}

虽然e1行调用MyType.equals,但e3e4不调用。我没有找到任何方法来说服它这样做。我尝试将签名更改为def equals(that: js.Any): Boolean,甚至是override def equals(that: Any): Boolean,仍然没有成功。

我能做的最好的事情就是使用====运算符:

代码语言:javascript
复制
object MyType {
  implicit class PimpEquals(val myType: MyType) {
    override def equals(that: Any): Boolean = {
      that match {
        case myTypeThat: MyType =>
          myType.equals(myTypeThat) // calls MyType.equals
        case _ =>
          myType.equals(that) // calls java.lang.Object.equals
      }
    }

    def ====(that: Any): Boolean = {
      equals(that)
    }
  }
}

(对于普通的==,不考虑pimped equals,考虑到该语言的定义方式,这并不奇怪)。尽管如此,====的问题是有人可能会错误地使用==操作符,并且没有得到任何警告。

有没有办法说服Scala.js使用JavaScript类提供的equals实现?如果不是,有什么方法可以使它在MyType上使用==时发出错误或警告(最好是在编译时

注意:在GitHub上可以找到完整的现成项目。

EN

回答 1

Stack Overflow用户

发布于 2018-10-05 04:31:26

我找到了部分答案。我可以使用@JSName重载==操作符。它不能被重写,因为它是最终的,但它可以被重载:

代码语言:javascript
复制
@js.native
class MyType(var x: Double, var y: Double) extends js.Any {
  def equals(that: MyType): Boolean = js.native

  @JSName("equals")
  def ==(that: MyType): Boolean = js.native

  @JSName("equalsNot")
  def !=(that: MyType): Boolean = js.native

  override def toString: String = js.native
}

请注意,我将以!=的形式导入equalsNot。这样的函数不存在,但是当有人试图使用!=时,我希望得到错误。如果没有重载,它将静默工作,但使用与==不同的语义。

我更喜欢以某种方式覆盖equals,以便使用==!=的自然Scala实现,但到目前为止我还没有找到一种方法。也许其他人可以提出一些更聪明的解决方案?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52625308

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档