open class X {
private fun m() = Unit
class Y : X() {
fun n() {
X().m() // 1
m() // 2
super.m() // 3
}
}
}
So (1) is ok, as expected. I would also expect (2) to be ok, but there is a compiler error along the lines “Cannot access ‘fun m(): Unit’: it is private in supertype X”. Interestingly, (3) also compiles.
I wonder whether this is intended, or maybe a compiler bug. At least the behavior is not derivable from the Kotlin spec.
open class X {
private fun m() = Unit
}
class Y : X() {
fun n() {
X().m() // 1
m() // 2
super.m() // 3
}
}
As you can see, m() is attempting to call X.m(), which is a private method of a super-type. This is not legal, as expected.
Just guessing, but if you’re coming from Java, you may be confusing nested classes (static class in Java, class in Kotlin) and inner classes (class in Java, inner class in Kotlin). With an inner class, your code compiles, though it’s extremely hard to understand due to having two different instances of X in scope with different state.
But that code isn’t quite the same, is it? As you say, Y is not an inner class — but in the question, it is a nested class. And so doesn’t Y get access to the internals of its outer class?
No, I think the reasons that m() fails are:
Unqualified m() refers to the outer class method, not that of the superclass (even though they’re the same code).
m() is an instance method, so needs an instance of X to receive a call.
Y is a nested class, and so (unlike an inner class) is not associated with an instance of X.
So the call is invalid because there’s no instance to receive it, not because the method is private.
(You can demonstrate this by making Y an inner class; it then compiles fine.)
The example is intended to be nested and not-inner. The variant where Y is outside is not the same, as then (1) also does not compile anymore. But as nested class, (1) does compile and that’s logical because m is visible inside X and also Y is inside X. The philosophical question is, why should this be different when m is accessed “through inheritance”. I don’t see why the rules of visibility should be dependent on the rules of inheritance.
In the meantime, I noticed that (3) throws a runtime IllegalAccessError. So there is at least one bug involved, for which I created a ticket: KT-72621 Errors when accessing private supertype callable from within nested class
Maybe the deeper reason for these problems are on Java bytecode level.