首页 文章

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

提问于
浏览
3

我即将使用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)extends gdx.math.Vector2(x,y){

我无法让这个工作 . 我也尝试了 var 而没有成功 java.lang.Float .

编辑:似乎这是不可能的,因为Scala生成一个函数,并且Java代码中没有等效函数 .

2 回答

  • 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 .

  • 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 = $ ”)}}

    运行此产生:

    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 的可用性 .

相关问题