Hey everyone, hope this is the right place to ask.
I’m using IntelliJ with Kotlin, and use the Lightweight Java Game Library (LWJGL) framework.
LWJGL has a set of OpenGL classes existing in packages within org.lwjgl.opengl.* (examples: org.lwjgl.opengl.GL20, org.lwjgl.opengl.GL43, etc. a class for each OpenGL version).
Anyways, say that I want to use method glDeleteShader, which exists in the class GL20, but that I have already imported org.lwjgl.opengl.GL43. (GL43 extends all the previous versions, so glDeleteShader is available). If I do autocomplete in IntelliJ, glDeleteShader will pop up as an option, but when I then press tab to autocomplete, IntelliJ will insist on doing a specific import to import org.lwjgl.opengl.GL20, and also prefix the method with GL20, so the line becomes GL20.glDeleteShader().
If I then remove the newly added import org.lwjgl.opengl.GL20 line, and remove the GL20 prefix, so that all that is left is glDeleteShader(), it still works just fine.
That’s the behaviour that I want, and I’m not sure what’s causing the other behaviour to take place instead. When using java with import static I experienced no such import problems.
I assume that this is a static method. Kotlin doesn’t allow you to use static methods from child classes. You have to directly point to the class that actually defines them. As such you will have to import the members of both.
1 Like
Yep, static classes. All right, just had to make sure that something weird wasn’t going on.
What I still don’t understand is that I can remove the import org.lwjgl.opengl.GL20 line, remove the GL20 prefix, and only keep the org.lwjgl.opengl.GL43 import, and it’ll compile just fine. So it seems like it’s not exactly necessary, but IntelliJ still insists on doing it.
The class for this example can be found on GitHub, here: https://github.com/LWJGL/lwjgl3/blob/master/modules/lwjgl/opengl/src/generated/java/org/lwjgl/opengl/GL43.java
I don’t have enough experience with Java and Kotlin to realize if I’m overlooking something fundamental here. But yes, I know that when using LWJGL with Java, the recommended pattern to use is static import for the OpenGL classes in order to avoid the GL class prefixes, however that still leaves me wondering why I seem to be able to do it in my code.
To give some short code examples to clear this up a bit in case it’s confusing. This will work and compile just fine:
import org.lwjgl.opengl.GL43.*
fun myOpenGlFunctionCall() {
glDeleteShader(1)
}
However, taking that same piece of code, and writing another call to glDeleteShader below the first one, using autocomplete in IntelliJ, will leave you with this:
import org.lwjgl.opengl.GL20
import org.lwjgl.opengl.GL43.*
fun myOpenGlFunctionCall() {
glDeleteShader(1)
GL20.glDeleteShader(1)
}
It will insist on prefixing with GL20, and do an import to import org.lwjgl.opengl.GL20, even though this is clearly not necessary.
In this because the line of glDeleteShader will in a sense be taken to be Java code, and not Kotlin code? Or am I missing something here?
Kotlin doesn’t allow you to use static methods from child classes
I believe @pdvrieze may have been referring to the Java antipattern (see Effective Java #17) of creating an interface that consists solely of constants, and then implementing said interface in order to have these constants in scope. (See ObjectInputStream
and its ObjectStreamConstants
for a somewhat prominent example.) Fortunately, this is indeed not supported in Kotlin.
If not, this isn’t entirely true. As you said, the code compiles fine.
However, it seems that while using static methods on an implementing class is supported, only the class that actually “defined” the method gets suggested in autocomplete. I can’t say that I have an idea as to why, though I feel this may simply be a bug/an oversight, as writing code like this is arguably suboptimal in most cases.
This is easily reproducible:
class A {
static void foo() {
}
}
class B extends A {
}
import B.foo
fun main() {
foo()
A.foo()
}
1 Like
Cheers for the clarification! Still not super experienced in Java / Kotlin, so I might have been a bit unclear in my description of the problem. But yes, that’s the exact problem I’m experiencing. While it might not be optimal code in most cases, yeah, it still seems like IntelliJ should behave better in these cases?
Since this seems like a bug you should create an issue here: https://kotl.in/issue
1 Like
A bug has been reported, and has been verified and reproduced here: https://youtrack.jetbrains.com/issue/KT-34955
1 Like