Cannot access Java static member inherited from another Java class

Hello,

EDIT: neglected to mention - this is for Scala 3.6.4.

I am attempting to replicate this example in Scala. This an example that uses the java FFM API to access the native GLUT library. The header files are used to extract and generate Java classes that access the underlying library.

The original code has something like:

import org.freeglut.*;
import static org.freeglut.freeglut_h.*;

...

    public static void main(String[] args) {
        try (var arena = Arena.ofConfined()) {
            var argc = arena.allocateFrom(C_INT, 0);
            ...
 

In Scala I have (just for testing):

import org.freeglut.freeglut_h_7
import org.freeglut.freeglut_h

object STeapot:

  @main
  def teapot() =
    import scala.util.{Try, Using}

    Using.resource( Arena.ofConfined() ) {
      arena => 
        val z = freeglut_h_7.C_INT
        val y = freeglut_h.C_INT
...

The declaration of z compiles just fine. The case of y fails with:

value C_INT is not a member of object org.freeglut.freeglut_h

The issue is that:

public class freeglut_h extends freeglut_h_1 
public class freeglut_h_1 extends freeglut_h_2 
public class freeglut_h_2 extends freeglut_h_3 
public class freeglut_h_3 extends freeglut_h_4
public class freeglut_h_4 extends freeglut_h_5
public class freeglut_h_5 extends freeglut_h_6 
public class freeglut_h_6 extends freeglut_h_7 
public class freeglut_h_7 {
...
    public static final ValueLayout.OfInt C_INT = ValueLayout.JAVA_INT;

The setup seems to allow access to all inherited members from Scala. Why is this not so? Short of having to search for and importing all class that are extended, what is the best way to circumvent this?

Please note that the header files are many and large and jextract creates many classes.

TIA

Sadly this is working as desired:

Scala simply doesn’t have the Java concept of statics. We have companion objects instead, but no inheritance relationship exists between the companion objects of a subclass and a superclass. Following Java here and allowing MyClass.myStaticBaseMethod wouldn’t be consistent with that.

Resolve inherited Java static method · Issue #7386 · scala/bug · GitHub


This has happened to me in the past, and it is really frustrating to have to go and look for the correct super type. I even end up replicating the API using export.

Which makes me wonder, if Scala 3 could fix this by using a hypothetical export.

2 Likes

What was the rationale for not including statics, or some way to do companion object inheritance / interface obligations? There are types of domain problems where this is the most natural and correct way of modeling, but is technically impossible in Scala (like how many OOP-friendly problems are made much harder in rust out of arbitrary decision to not include inheritance for religious reasons; was this a similar story for Scala?)

@BalmungSan Thank you. Fortunately here I don’t seem to need exports. I do have to import all classes separately though.

I guess you could say it’s kind of a similar story, but then actually completely the other way around. When Scala was created it was very religious about being 100% Object-Oriented. I.e. everything is an object. And with static methods, there is no object to call the method on.

2 Likes

The object could have been the class itself, if classes were themselves objects (if truly everything is an object) as they are in python/javascript. (This would also allow passing around classes as values nicely, something that is very irritating to do in scala and kotlin (e.g. classOf[...], Kclass ::class))

Well, an object CAN’T inherit from another object, as simple as that.
Inheritance is a property of classes (not values), not of objects (values).

The fact that in Java statics are inherited is just a consequence of Java not being pure OOP compared to Scala.

Again, I can only think of only one “correct” way to fix this in a pure OOP language like Scala is through the use of export, but not sure how costly that can be.
Ideally, it would be fully contained at compile time and just inline the right call in the bytecode, so probably the only cost would be in the implementation overhead.

Well, you may create a new thread explaining your problem and we may suggest alternatives.

For the record, I have yet to see a problem where full OOP was useful.
However, sure, basic subtyping (a property of type theory, not of OOP) is indeed useful, but it also carries a lot of indirect complexity.

I only meant inheritance hierarchies. There are problems where inheritance is the best possible representation, and any alternatives are slightly or significantly worse on what they can express or how cumbersome they are to implement. So, if you use a language like rust, you have to accept this sacrifice that in some problem domains you will be forced to use strictly worse alternatives (and for religious reasons of the language creators at that) instead of the tool made for the job: inheritance.