在Scala中扩展Java类,同时保持字段可访问

时间:2014-04-07 15:41:32

标签: java scala libgdx

我即将使用LibGDX写一个2D游戏,它有很好的类Vector2

由于我以功能性的方式写作(复制,模式匹配等),我希望它能成为一个案例类。

因为它不是一个,所以我决定尝试扩展它而没有成功:

import com.badlogic.gdx

class Vector2(x: Float, y: Float) extends gdx.math.Vector2(x, y) {
  def copy(x: Float = this.x, y: Float = this.y): Vector2 = {
    new Vector2(x, y)
  }
}

object Vector2 {
  def apply(x: Float = 0, y: Float = 0): Vector2 = {
    new Vector2(x, y)
  }
}

问题是以下内容会引发println(Vector2(1, 2).x),因为没有x字段。

如果我像class Vector2(override val x: Float, override val y: Float)那样写它会抛出:

  

在Float类型的Vector2类中覆盖变量x;值x有   不兼容的类型类Vector2(覆盖val x:Float,   override val y:Float)扩展gdx.math.Vector2(x,y){

我无法让这个工作。我还尝试varjava.lang.Float没有成功。

编辑:似乎不可能,因为Scala生成了一个函数,并且Java代码中没有相应的函数。

2 个答案:

答案 0 :(得分:2)

您正在隐藏您想要的x

人们常常因为需要重命名类参数以避免创建字段而烦恼。

请参阅this symptomthe shadowing issue

在这种情况下,它会导致互操作问题。

scala> :pa
// Entering paste mode (ctrl-D to finish)

class Vector2(x0: Float, y0: Float) extends gdx.math.Vector2(x0, y0) {
  def copy(x: Float = this.x, y: Float = this.y): Vector2 = {
    new Vector2(x, y)
  }
}

object Vector2 {
  def apply(x: Float = 0, y: Float = 0): Vector2 = {
    new Vector2(x, y)
  }
}

// Exiting paste mode, now interpreting.

defined class Vector2
defined object Vector2

scala> Vector2(1, 2).x
res1: Float = 1.0

脚注:

前,

scala> Vector2(1, 2).x
java.lang.IllegalAccessError: tried to access field Vector2.x from class 
  ... 40 elided

因为this.x在子类中创建了一个私有字段。

错误的表达不应该试图访问该字段;如果没有访问者x,它应该

scala> (Vector2(1,2): gdx.math.Vector2).x
res2: Float = 1.0

您无法绕过super.x的阴影,因为它不是def

答案 1 :(得分:0)

我尝试了很多东西,看起来你在编辑中得出的结论是正确的。

然而,有一种更迂回的方式来完成这项工作:

package rrs.scribble

import  com.badlogic.gdx.math

class Vector2(x: Float, y: Float) {
  val gdxV2 = new math.Vector2(x, y)
}

object Vector2 {
  implicit class V2(v2: Vector2)
  extends math.Vector2(v2.gdxV2)
}

object  Demo {
  import Vector2._

  def main(args: Array[String]) {
    val v2a = new Vector2(12.34f, 56.78f)
    val v2b = new Vector2(12.345f, 56.789f)

    println(s"v2=$v2a; v2=$v2a; sum=${v2a.add(v2b)}")
    println(s"(v2a =E(0.01) v2b)=${v2a.epsilonEquals(v2b, 0.01f)}")
    println(s"(v2a =E(0.001) v2b)=${v2a.epsilonEquals(v2b, 0.001f)}")

    // Note: This won't compile, apparently because
    // hasOppositeDirection is inherited not implemented within Vector2

// println(s" v2 = $ v2a; sum = $ sumA; hasOppositeDirection = $ {v2.hasOppositeDirection}")        }     }

运行此产生:

scala> rrs.scribble.Demo.main(Array[String]())
v2=rrs.scribble.Vector2@6e8d0165; v2=rrs.scribble.Vector2@6e8d0165; sum=[24.685001:113.569]
(v2a =E(0.01) v2b)=true
(v2a =E(0.001) v2b)=false

不幸的是,正如评论所指出的那样,Vector2继承的方法似乎失败了。实际上,我不确定为什么会这样。然而,这种方法还有一个优点。例如,您可以在+上定义-V2等,以增强基础gdx.math.Vector2的可用性。