繁体   English   中英

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

[英]How to convince Scala.js to use Javascript defined method equals for comparison?

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

我有一个Java语言类型,它定义了equals方法:

MyType.js:

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门面:

@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类提供的用于比较的对象。

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

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.equalse3e4则不行。 我没有找到任何方法可以说服它这样做。 我试过将签名更改为def equals(that: js.Any): Boolean甚至override def equals(that: Any): Boolean ,仍然没有运气。

我能做的最好的事情是====操作符并使用它:

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)
    }
  }
}

(对于普通== ,不考虑带有条件的equals ,鉴于语言的定义,这不足为奇)。 ====的麻烦仍然是有人可以错误地使用==运算符,并且不会给出警告。

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

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

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

@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实现,但是到目前为止,我还没有找到解决方法。 也许其他人能够提供一些更智能的解决方案?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM