I apparently don’t understand Kotlin’s rules of inheritance. In Java, any protected variable would be available in any subclass of the variable’s containing class. In Kotlin, these rules don’t seem to apply. I’m getting a compile error 'logger' has private access in com.example.MainActivity.
Kotlin code of interest:
package com.example.ui
abstract class MainActivity : Activity() {
protected val logger = LoggerFactory.getLogger(this.javaClass)
//... other classy stuff...
}
Java subclass:
package com.example.ui;
public class MobileMainActivity extends MainActivity {
@Override
public void onCreate(Bundle savedInstanceState) { //superclass derives from Activity; this is fine
//red squiggly, logger is not available, even though it's protected, in the same package, and inherits from MainActivity
logger.info("Sending multicast message for configuration...");
}
}
What am I missing? When I read the documentation, Kotlin appears to treat protected variables the same as Java does.
Kotlin docs:
https://kotlinlang.org/docs/visibility-modifiers.html#class-members
Am I forced to use getLogger() accessor rather than the variable itself? Doesn’t this make it actually private rather than protected within Java? Why? According to the documentation it shouldn’t… Where can I find information about the discrepancies when building a mixed language project with Kotlin and Java? It seems like this could complicate migration efforts, but I suppose it couldn’t be perfect…
>Solution :
Am I forced to use
getLogger()accessor rather than the variable itself?
No, you can add @JvmField to make a Kotlin property compile into a field in Java.
@JvmField
protected val logger = ...
This gives you a protected field in Java, and the getLogger method will no longer be available.
Doesn’t this make it actually private rather than protected within Java?
No. getLogger is a protected method in Java.
Rather than documentation about the Kotlin language in general, you should look at the Kotlin-Java interop documentation when you are working in both languages. It very clearly says that a private field is generated for every Kotlin property, when it has a backing field:
A Kotlin property is compiled to the following Java elements:
- a getter method, with the name calculated by prepending the
getprefix- a setter method, with the name calculated by prepending the
setprefix (only forvarproperties)- a private field, with the same name as the property name (only for properties with backing fields)