首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Scala运算符添加到最终的Java类

将Scala运算符添加到最终的Java类
EN

Stack Overflow用户
提问于 2012-06-12 20:34:22
回答 4查看 843关注 0票数 3

我在Scala中使用jMonkeyEngine (JMonkeyEngine),到目前为止,它运行得很好,但现在我想问自己,是否有一种为Vector3f (和类似的)类重载操作符的优雅方法。我的第一个想法是继承Vector3f并重载操作符,但是Vector3f是最终的,所以这不是一个选项。接下来,我想也许我可以有一个带有静态方法的单例/scala对象,这些方法可以在Vector3f上运行,如下所示,但这也是行不通的:

代码语言:javascript
复制
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方法。然而,这有三个缺点:

  1. 我将不得不对许多来回转换( toVector3ffromVector3f方法或类似的东西)进行处理。
  2. 当我有Vector3f/ScalaVectors数组时,这个问题就变得更糟了。由于类是不相关的(除了通过组合),每次在jME中调用方法时,我都必须手动转换数组的每个元素。
  3. 即使这样,我也不知道如何为我的新ScalaVector类重载一个操作符,这样我就可以在前面有一个因子,即1.2f * v

我的问题是:有人能想出一种方法来使这个更自然/优雅吗?你如何处理类似的问题?或者,是否有我所知道的Scala语法来做这些事情?在C++中,我将创建一个全局操作符,它以float和Vector3f作为参数,并可能使其成为朋友。Scala是如何做到这一点的,还是说这根本不可能?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-06-12 20:44:30

或者有没有我不知道的Scala语法来做这类事情?

是啊,有种说法是:

代码语言:javascript
复制
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)

由于Scala2.10的隐式转换也可以编写为:

代码语言:javascript
复制
implicit class VectorMath(f: Float) { def * (v: Vector3f) = v mult f }

自2.10以来,还有一些值类由编译器优化以获得更好的性能:

代码语言:javascript
复制
implicit class VectorMath(val f: Float) extends AnyVal { def * (v: Vector3f) = v mult f }
票数 12
EN

Stack Overflow用户

发布于 2012-06-12 21:01:17

除了上面提到的隐式类(从Scala2.10开始)之外,您还可以使用价值类来避免创建中间对象。

本质上,您只需使VectorMath在扩展AnyVal上面。如果您不使用VectorMath对象作为方法的返回值,而只是调用VectorMath操作,则不会在运行时为VectorMath分配任何对象。

票数 3
EN

Stack Overflow用户

发布于 2012-06-12 20:45:05

注意事项:这可能导致非常不可读的代码。

您可以使用隐式转换,并在Vector3f周围创建某种包装类(比如Scala标准库本身有几个Java类,例如请看这里集合)。

代码语言:javascript
复制
// Somewhere, for example in a package object
implicit def wrapVector3f (v: Vector3f) = new Vector3fWrapper ( v );

class Vector3fWrapper (v: Vector3f) {
    // Use the Vector3f object internally here
    // You can now delegate all methods to the underlying Vector3f object
    // For example:
    def * (v: Vector3f) = {
        // ...
    }

    // or:
    def * (f: Float) = {
        // ...
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11004444

复制
相关文章

相似问题

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