Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将Scala操作符添加到最终的Java类中_Java_Scala_Overloading_Operator Keyword_Final - Fatal编程技术网

将Scala操作符添加到最终的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,

我在Scala中使用了jMonkeyEngine(Java游戏引擎),到目前为止效果很好,但现在我在问自己是否有一种优雅的方式来重载
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
    的方法或者类似的东西)
  • 当我有向量3f/ScalaVectors数组时,这个问题变得更糟。由于这些类不相关(除了通过组合),因此每次调用jME中的方法时,我都必须手动强制转换数组的每个元素
  • 即使这样,我也不知道如何为我的新ScalaVector类重载运算符,使其能够将因子放在前面,即
    1.2f*v
  • 我的问题是:有人能想出一种方法让它更自然/优雅吗?你如何处理类似的问题?或者我不知道有没有一种Scala语法来做这类事情?在C++中,我将生成一个全局算子,它以浮点和向量3f作为参数,并可能与之相交。Scala是如何做到这一点的,还是根本不可能

    或者可能有一种Scala语法,我不知道它能做这些事情吗

    是的,这里有:

    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