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.
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.
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.
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.
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?)
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.
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 Javastatics 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.