Probably already been proposed but "private inheri...
# language-proposals
e
Probably already been proposed but "private inheritance":
Copy code
interface Foo
class MyClass : private Foo
Unless I'm missing something it's more memory efficient than dedicating a private/protected field to an instance of Foo to be used internally.
l
How should
myObject is Foo
behave when
myObject
is of type
MyClass
?
g
But how is it more memory efficient, maybe I'm missing something. What is even a use case for it?
k
I'm not convinced that we need private inheritance in Kotlin, but to answer the above questions, I would look into how private inheritance works in C++. There, private inheritance is something that only the inheriting class concerns itself with. Thus
myObject is Foo
would be false, since it's not anyone's concern that MyClass privately inherits Foo. It's slightly more memory efficient (in typical implementations) because it avoids having a reference to a private member object. It's basically the same memory as publicly extending a class, except it does it privately. In C++, where private inheritance has been there from the beginning, it's very rarely used. One common use is in the Adapter design pattern, where the adaptee is privately inherited while the target is publicly inherited. This is just a minor convenience, as the pattern can easily be implemented without private inheritance.
šŸ‘ 2
g
Thanks for the explanation!
Itā€™s slightly more memory efficient (in typical implementations) because it avoids having a reference to a private member object
I doubt that any implementation which Kotlin could provide would be more memory efficient, at least on JVM, it anyway will be just a syntactic sugar on level of JVM and it would work as implicit delegation to private parent class
ā˜šŸ¼ 1
šŸ‘šŸ» 1
l
It'd also be weird to have the
is
check always be false, even within the class, or be true only when within the class. Therefore, I think it should not be a feature because of the added confusion
šŸ‘šŸ¼ 1
šŸ‘šŸ» 1
e
The
is
check would be true within the class but false outside. I'm not sure I understand why the implementation wouldn't perform identically to the public inheritance. I can formulate a more reasonable example but I was testing an idea I had and was thinking it would be handy. Don't mind the rest of the code it's messy and unsafe. https://srcb.in/3vj3x9zJkC In this case, STreeEvent would only publically extend
suspend (SToggled, Boolean, Listener) -> (Unit)
The only way to do that currently is to have an inner class that extends everything else and keep an instance of that in each STreeEvent.
g
The only way to do that currently is to have an inner class that extends everything else and keep an instance of that in each STreeEvent
This how JVM works, you really cannot avoid it with any kind compiler magic, at least I donā€™t see how itā€™s possible. If keeping 32/64 bit reference + 32/64 bit on minimal object on each instance is too big overhead for you, it really looks that you need some kind specialised data structure for this , not classic objects But I honestly doubt that it would be any kind significant difference which can be measured, especially in such coroutines and lambdas heavy code
šŸ‘šŸ¼ 1
šŸ‘šŸ» 1
I understand why the implementation wouldnā€™t perform identically to the public inheritance.
But how this implementation can be theoretically implemented on jvm?
If you want to hide letā€™s say implementation of
suspend (SUpdate<Listener>) -> (Unit)
you just create internal class, as you said, just keep anonymous instance in private/internal property. Overhead will be only 1 additional anonymous class and one additional reference field So in terms of code it would be almost identical, no additional boilerplate (also arguably more readable). On runtime yes, a bit more, but saving a single object in this code looks as very small overhead
e
Yeah that's fair enough, once you get out of the CPP mindset you are probably right! "But how this implementation can be theoretically implemented on jvm?" Ah you mean to ensure visibility is correct when calling via Java?
g
Right, not even via Java, but how to make it visible for JVM runtime to be even called (runtime itself is strongly typed, you cannot call arbitrary method by name without reflection). So JVM will require some class instance anyway. So it should be some class instance of correct type which implements this interface even to be able to compile to correct class file (itā€™s similar to what already happening every time when you use any lambda), which in terms of runtime is the same as private/internal property with anonymous class
k
Andrey, I'm not sure I fully understand. Why isn't it possible to have
Copy code
interface Foo
class myClass : private Foo
be compiled into the same bytecode as this:
Copy code
interface Foo

@__kotlin_special_annotation_saying_Foo_is_privately_inherited
class myClass : Foo // public inheritance!
The the JVM can see the inheritance, but the Kotlin compiler (only) knows it's private.
g
So it will have real inheritnace and will be just restricted on level of Kotlin compiler Itā€™s possible, but it also possible to call it from java Also this ā€œThus
myObject is Foo
would be falseā€ will not be false anymore, because class actually implements foo It also means that anyone can cast it to Foo and call those methods
So it already looks as different semantics comparing to what you described for C++
k
But then in Kotlin the definition of the
is
operator would be augemented to check the special annotation as well as inheritance, and thus would return false due to the presence of the annotation. (Java would ignore the annotation and treat the inheritance as public, but there are already existing limitations to the interoperability and this will be just another one.)
Also, compare this with a similar Kotlin compiler "trick": the
internal
access modifier doesn't exist in the JVM. So internal classes are compiled into bytecode that treats them as public classes, with an annotation. Only the Kotlin compiler knows they're internal (Java can access internal classes as though they were public). The same trick can be applied to private inheritance.
g
But then in Kotlin the definition of the
is
operator would be augemented
So it will be converted from JVM INSTANCEOF instruction to some custom code, which actually checks that this class is Kotlin class
Which also binary incompatible
I agree, itā€™s a trick, but some tricks just better than another