将Scala操作符添加到最终的Java类中
我在Scala中使用了jMonkeyEngine(Java游戏引擎),到目前为止效果很好,但现在我在问自己是否有一种优雅的方式来重载将Scala操作符添加到最终的Java类中,java,scala,overloading,operator-keyword,final,Java,Scala,Overloading,Operator Keyword,Final,我在Scala中使用了jMonkeyEngine(Java游戏引擎),到目前为止效果很好,但现在我在问自己是否有一种优雅的方式来重载Vector3f(和类似的)类的操作符。我的第一个想法是继承Vector3f并重载操作符,但是Vector3f是最终的,所以这不是一个选项。接下来,我想也许我可以拥有一个singleton/scala对象,该对象具有在Vector3f上操作的静态方法,如下所示,但这也不起作用: object VectorMath { def *(factor: Float,
Vector3f
(和类似的)类的操作符。我的第一个想法是继承Vector3f
并重载操作符,但是Vector3f
是最终的,所以这不是一个选项。接下来,我想也许我可以拥有一个singleton/scala对象,该对象具有在Vector3f
上操作的静态方法,如下所示,但这也不起作用:
object VectorMath {
def *(factor: Float, vector: Vector3f) = vector.mult(factor)
}
//and then somewhere
import VectorMath._
var v = new Vector3f(1,2,3);
var u = 1.2f * v; //this does not work, because Float does not have * overloaded for Vector3f
var u = VectorMath.*(1.2f, v); //this does work, but defeats the purpose
因此,我现在所能想到的就是将Vector3f封装在一个新的Scala类中,并将操作符调用委托给适当的Java方法。然而,这有三个缺点:
到vector3f
和一个到vector3f
的方法或者类似的东西)1.2f*v
class VectorMath(f: Float) { def * (v: Vector3f) = v mult f }
implicit def VectorMath(f: Float) = new VectorMath(f)
val v = new Vector3f(1,2,3)
1.2F * v
// treated as: VectorMath(1.2F).*(v)
由于Scala 2.10,隐式转换也可以写成:
implicit class VectorMath(f: Float) { def * (v: Vector3f) = v mult f }
从2.10开始,还有一些值类由编译器优化以获得更好的性能:
implicit class VectorMath(val f: Float) extends AnyVal { def * (v: Vector3f) = v mult f }
注意:这可能导致代码非常不可读 您可以使用隐式转换并围绕
Vector3f
创建某种包装类(比如Scala标准库本身和几个Java类,比如Java集合)
除了上面提到的隐式类之外,从Scala 2.10开始,您还可以使用避免创建中间对象
本质上,您只需在上面扩展
AnyVal
就可以了。如果您不使用VectorMath
对象作为方法的返回值,而只调用VectorMath
操作,那么运行时将不会为VectorMath
分配任何对象。class Vector3f(…) {
…
def *:(f: Float) = …
}
var v = new Vector3f(1,2,3);
var u = 1.2f *: v; //this works without any implicit magic or boxing overhead
它需要一个小的语法惩罚,但这是另一种选择。这种方法的问题是,Vector3f是来自jMonkeyEngine的
最终类。
。因此,您不能扩展它并添加自己的方法,在您的解决方案中是如何隐式完成的。k,因此隐式地将它拉上是解决方案–只是想表明存在一个可选方法可用。注意:这需要放在对象中,而不是放在顶部作用域中。要使用隐式转换,需要导入该对象。(Scala专家可能很清楚,这不适合我,因此我添加了此注释)。
class Vector3f(…) {
…
def *:(f: Float) = …
}
var v = new Vector3f(1,2,3);
var u = 1.2f *: v; //this works without any implicit magic or boxing overhead