Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending a Java class in Scala while keeping the field accessible

Tags:

java

scala

libgdx

I'm about to write a 2d game using LibGDX which has nice classes like Vector2.

Since I'm writing in functional fashion (copying, pattern matching, etc.) I'd like it to be a case class.

Because it's not one, I decided to try to extend it without success:

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)
  }
}

The problem is that the following throws println(Vector2(1, 2).x) because there's no x field.

If I write it like class Vector2(override val x: Float, override val y: Float) it throws:

overriding variable x in class Vector2 of type Float; value x has incompatible type class Vector2(override val x: Float, override val y: Float) extends gdx.math.Vector2(x, y) {

I'm unable to get this to work. I also tried var instead and java.lang.Float without success.

Edit: It seems that it's not possible, because Scala generators a function and there's no equivalent function in Java code.

like image 301
Kai Sellgren Avatar asked Jun 10 '26 17:06

Kai Sellgren


1 Answers

You are shadowing the x you want.

People are often annoyed by this need to rename class parameters to avoid creating fields.

See this symptom and the shadowing issue.

In this case, it results in an interop problem.

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

Footnote:

Before,

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

because this.x creates a private field in the subclass.

The erroneous expression shouldn't be trying to access that field; in the absence of an accessor x, it should

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

You can't circumvent the shadowing with super.x, because it's not a def.

like image 120
som-snytt Avatar answered Jun 12 '26 07:06

som-snytt