Java access to val inside companion object

I have a Scala class in package things, which defines a val inside a companion object, like this (these are all fictitious names to protect the innocent):

package things

class Brick

  object Brick
    val prototype: Brick = theExpressionToDefinePrototype

Then within Java code I want to refer to prototype like the static variable it is:

  ... Brick.prototype  ...

However, Brick can’t be resolved in the Java code. I have tried importing it by

import things.Brick;

in which case prototype can’t be resolved, or by

import things.Brick.*;

or

import static things.Brick.*;

in which case Brick can’t be resolved. How can I refer to Scala’s Brick.prototype within Java code? Thanks.

You’d need to refer to module class emitted by the compiler, here’s an example from the Scala compiler test suites scala/test/files/pos/t7847 at 1c9aa590ba5c26e044904d1c9a26aaf3b29cae73 · scala/scala · GitHub

In you’re case that would probably be Brick$.MODULE$.prototype I’m not sure, but this field might be probably emitted as private in JVM bytecode, so you’d need to access the prototype() getter or prototype_= setter in case of vars

Scala should normally create static forwarders that are usable from Java:

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

class Test { def test = "test" }
object Test { def foo = 42; val bar = 7 }

// Exiting paste mode... now compiling with scalac.

scala> :javap -p Test
Compiled from "<pastie>"
public class Test {
  public static int bar();
  public static int foo();
  public java.lang.String test();
  public Test();
}

That’s what Scala 2 did at least. I would think that Scala 3 should still do the same thing unless it only special cases main methods or something like that…

Note that these forwarders are methods, though - the Java side would have to access Brick.prototype() in the OP’s example.

1 Like

Ah I missed that it was about accessing a field. That indeed will never work as far as I know. Scala makes all fields private, only the accessor methods (and mutators for var) can be made public. That’s what enables things like overriding a def with val for example.

@Jasper-M Bingo! Yes, it is about accessing a field. That seems to be the issue. Now that I know that, I can rewrite the code to do something a bit more idiomatic. This is part of a larger system that will probably benefit by doing this part differently.

1 Like

(As an aside: instead of posting English descriptions of error messages, please post actual complete error messages — it makes it easier to help, by reducing the amount of guesswork we have to do.)

1 Like

Wasn’t it sufficient to add the (), as @sangamon suggested?

1 Like