背景:真实的项目使用带有的。Three.js和facade都为许多类型定义了equals
方法,包括Vector3
__。这是一个演示equals
功能的小示例。
我有一个Javascript类型,它定义了一个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.equals
,但e3
和e4
不调用。我没有找到任何方法来说服它这样做。我尝试将签名更改为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)
}
}
}
(对于普通的==
,不考虑pimped equals
,考虑到该语言的定义方式,这并不奇怪)。尽管如此,====
的问题是有人可能会错误地使用==
操作符,并且没有得到任何警告。
有没有办法说服Scala.js使用JavaScript类提供的equals
实现?如果不是,有什么方法可以使它在MyType
上使用==
时发出错误或警告(最好是在编译时
注意:在GitHub上可以找到完整的现成项目。
发布于 2018-10-05 04:31:26
我找到了部分答案。我可以使用@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实现,但到目前为止我还没有找到一种方法。也许其他人可以提出一些更聪明的解决方案?
https://stackoverflow.com/questions/52625308
复制相似问题